繁体   English   中英

从python运行时,Docker映像给我“在$ PATH中找不到可执行文件”

[英]Docker image gives me “executable file not found in $PATH” when run from python

我正在尝试在python的docker映像内运行一些命令。 当我做:

docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh -c "javac example.java && java example"

在控制台(kali linux)中,它可以正常运行并打印结果。 当我尝试从python运行相同的命令时,出现以下错误:

"Exception: docker: Error response from daemon: oci runtime error: exec: \"sh -c 'javac example.java && java example'\": executable file not found in $PATH.\n"

这些行从python正常工作:

docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim javac
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim javac example.java

但是这些不是:

docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh javac
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh javac example.java
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh -c javac
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh -c "javac"

它们都可以通过控制台工作。 只是不是来自python。 一旦添加“ sh -c”,它就会给我错误。 我可以将其作为2个单独的命令运行,例如:

docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim javac example.java
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim java example

但重要的是,它必须一次全部运行。

在控制台上一切正常,但是在python中,只要我添加“ sh -c”,它就会给我错误。 我究竟做错了什么?

这是我使用的python代码:

BASE_CMD = [
    'docker',
    'run',
    '--rm',
    '-v'
]

def calculate_compile_and_execute_java_command(folder_name, file_name):
    return BASE_CMD + [
        folder_name + ":/mnt",
        "--workdir",
        "/mnt",
        "frolvlad/alpine-oraclejdk8:slim",
        "sh -c 'javac " + file_name + " && java " + file_name[:-5] + "'"
    ]
.
.
.
response = call_command(calculate_compile_and_execute_command(self.lang, file_path, file_name))
.
.
.
def call_command(cmd, timeout=float('inf'), cwd=None, decode=True, **subproc_options):
    if cwd is None:
        cwd = os.getcwd()

    subproc = subprocess.Popen(
        cmd,
        cwd=cwd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        **subproc_options
    )
    .
    .
    # code for timeout handling and result polling
    .
    .

我尝试了在计算方法中字符串连接和引号转义的所有可能组合。 Popen()将字符串发送到终端。 只是不适用于“ sh -c”。 如果我在命令中添加更多开关,它甚至可以工作。 像这样:

def calculate_compile_and_execute_c_command(folder_name, file_name):
    return BASE_CMD + [
        folder_name + ':/mnt',
        'frolvlad/alpine-gcc',
        'gcc',
        '--static',
        '/mnt/' + file_name,
        '-o',
        '/mnt/qq'
    ]

这给出了这样的字符串:

docker run --rm -v "$(pwd)":/mnt --workdir /mnt frolvlad/alpine-gcc gcc --static qq.c -o qq

您正在将一个大字符串作为最后一个参数传递给Docker。 Docker试图运行一个名为sh -c 'javac example.java && java example'的二进制文件,该二进制文件显然不存在。

您要使用2个参数运行sh二进制文件。 -c和要sh运行的shell脚本。

return BASE_CMD + [
    folder_name + ":/mnt",
    "--workdir",
    "/mnt",
    "frolvlad/alpine-oraclejdk8:slim",
    "sh", 
    "-c",
    "javac " + file_name + " && java " + file_name[:-5]
]

如果命令行脚本过于复杂,则可以将其隐藏在Shell脚本后面

#!/bin/sh
set -ue
javac $1
java ${1%.*}

然后

$ compile_and_run.sh whatever.java

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM