无法在 Docker 容器内的 Celery Worker 中获取 Bash 脚本输出

Cannot get Bash script output in Celery Worker inside Docker Container

对于这个问题,我真的很紧张。最近我开始研究远程代码执行服务。

该服务向 Celery worker 发送以下负载:

{
 "language": "python",
 "code": "print('Hello World!')"
}

服务期望接收回代码的输出。

Celery worker 在 docker 容器中运行,具有以下 Dockerfile:

FROM python:3.9-slim-buster

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONBUFFERED 1

RUN mkdir /worker
WORKDIR /worker

COPY requirements.txt /worker/


RUN /usr/local/bin/python -m pip install --upgrade pip

RUN pip install -r /worker/requirements.txt

COPY . /worker/

对于服务和工作人员,我正在使用 docker-compose 文件:

version: "3"

services:
  rabbit:
    image: rabbitmq:latest
    ports:
      - "5672:5672"
  api:
    build: app/
    command: uvicorn remote_coding_compilation_engine.main:app --host 0.0.0.0 --reload
    volumes:
      - ./app:/app
    ports:
      - "8000:8000"

  worker:
    build: worker/
    command: watchmedo auto-restart --directory=./ --pattern=*.py --recursive -- celery --app=worker.celery_app worker -c 2 --loglevel=INFO
    #celery --app=worker.celery_app worker -c 2 --loglevel=INFO
    volumes:
      - ./worker:/worker
    depends_on:
      - api
      - rabbit

  flower:
    image: mher/flower
    command: ["flower", "--broker=pyamqp://guest@rabbit//", "--port=8888"]
    ports:
      - "8888:8888"
    depends_on:
      - api
      - rabbit
      - worker

worker用payload中给出的代码创建一个.py文件,然后运行一个bash脚本来执行代码,代码输出应该是自动的从 python 重定向到 out_file。但是我无法获得 bash 脚本的输出。

这是 bash 脚本:

#!/bin/bash 

if [ $# -lt 1 ]
then
    echo "No code running command provided!"
else
    eval $@
fi

我将以下参数传递给此脚本:python path_to_file

这是运行 bash 脚本的工作代码:

def execute_code(cls, command: str, out_file_path: str) -> None:
        """
        Function which execudes the given command and outputs the result in the given out_file_path

        @param command: command to be executed
        @param out_file_path: path to the output file

        @return None

        @raise: FileNotFoundError if the command does not exist
        @raise: IOError if the output file cannot be created
        @raise: CalledProcessError if the command fails to be executed
        """
        try:
            logging.info(f"Creating output file: {out_file_path}")
            with open(out_file_path, "w+") as out_file_desc:

                logging.info(f"Creating process with command: {command} and output_file: {out_file_path}")
                os.chmod(cls.EXECUTE_CODE_SCRIPT_PATH, 0o755)

                rc = subprocess.call(command, shell=True, stdout=out_file_desc, stderr=out_file_desc)

                logging.info(f"Commandmd: {command.split()}")
                logging.info(f"Return Code: {rc}")
                logging.info(f"OutFile Content: {out_file_desc.read()}")

                if rc != 0:
                    logging.debug(f"Command execution was errored: {out_file_desc.read()}")
                    raise subprocess.CalledProcessError(rc, command)

        except FileNotFoundError as fnf:
            logging.error(
                f"Command not found: {command}"
            )
            raise fnf
        except IOError as ioe:
            logging.error(
                f"Could not create output file: {out_file_path}"
            )
            raise ioe
        except subprocess.CalledProcessError as cpe:
            logging.error(
                f"Process exited with error: {cpe.output}"
            )
            raise cpe

Obs1。 subprocess.call中执行的命令格式为/worker/execute_code/code_execute.sh python /worker/tmp/in_files/some_file_name.py

观察2。我确定脚本会运行命令,因为例如,如果我更改包含要执行的代码的文件夹的路径,我会收到“FileNotFound”错误。

观察3。如果我使用字面上的 python <> 而不是“$@”,我可以看到 bash 脚本

的输出

Obs4。 运行 实体对输出文件具有读写访问权限。即使我使用默认的 stdout

,我也无法获得脚本的输出

我尝试过的:

任何帮助将不胜感激,谢谢!

我相信您最初的直觉是正确的,根本不必维护 bash 文件。如果我正确理解您要执行的操作(执行命令,将输出写入文件),则无需维护 bash 脚本或将命令写入输入文件以开头:

def execute_code(command="print('Hello World')", out_file_path='/home/geo/result.txt'):
    with open(out_file_path, 'w+') as f:
        subprocess.Popen(["python", "-c", command], stdout=f)

您应该会在 result.txt 中看到输出。