I'm trying to run some commands inside a docker image in python. When I do:
docker run --rm -v <some_dir>:/mnt --workdir /mnt frolvlad/alpine-oraclejdk8:slim sh -c "javac example.java && java example"
In console (kali linux) it runs fine and prints the result. When I try to run same command from python it gives me the error:
"Exception: docker: Error response from daemon: oci runtime error: exec: \"sh -c 'javac example.java && java example'\": executable file not found in $PATH.\n"
These lines work fine from 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
But these don't:
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"
They all work from console. Just not from python. As soon as I add "sh -c" it gives me the error. I can run it as 2 separate commands like:
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
But it's important that it runs all at once.
It all works fine from console, but in python as soon as I add "sh -c" it gives me the error. What am I doing wrong?
Here is the python code that I use:
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
.
.
I tried all possible combinations of string concatenation and quotes escaping in calculate method. Popen() sends the string to terminal as it should. It just doesn't work with "sh -c". It even works if I add more switches to the command. Like this:
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'
]
Which gives the string like this:
docker run --rm -v "$(pwd)":/mnt --workdir /mnt frolvlad/alpine-gcc gcc --static qq.c -o qq
答案 0 :(得分:0)
您将一个大字符串作为最后一个参数传递给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