bash 将带有参数的命令作为字符串传递给 docker run

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39443913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:09:25  来源:igfitidea点击:

Passing a command with arguments as a string to docker run

linuxbashshelldockervariable-expansion

提问by davidA

The issue I'm facing is how to pass a command with arguments to docker run. The problem is that docker rundoes not take command plus arguments as a single string. They need to be provided as individual first-class arguments to docker run, such as:

我面临的问题是如何将带参数的命令传递给docker run. 问题是docker run不将命令加参数作为单个字符串。它们需要作为单独的一流参数提供给docker run,例如:

#!/bin/bash
docker run --rm -it myImage bash -c "(cd build && make)"

However consider the command and argument as the value of a variable:

但是,将命令和参数视为变量的值:

#!/bin/bash -x
DOCKER_COMMAND='bash -c "(cd build && make)"'
docker run --rm -it myImage "$DOCKER_COMMAND"

Unfortunately this doesn't work because docker rundoesn't understand the substitution:

不幸的是,这不起作用,因为docker run不理解替换:

+ docker run --rm -it myImage 'bash -c "(cd build && make)"'
docker: Error response from daemon: oci runtime error: exec: "bash -c \"(cd build && make)\"": stat bash -c "(cd build && make)": no such file or directory.

A slight change, removing the quotation of DOCKER_COMMAND:

略有变化,删除了引用DOCKER_COMMAND

#!/bin/bash -x
DOCKER_COMMAND='bash -c "(cd build && make)"'
docker run --rm -it myImage $DOCKER_COMMAND

Results in:

结果是:

+ docker run --rm -it myImage 'bash -c "(cd build && make)"'
build: -c: line 0: unexpected EOF while looking for matching `"'
build: -c: line 1: syntax error: unexpected end of file

How can I expand a string from a variable so that it is passed as a distinct command and arguments to docker runinside a script?

如何从变量扩展字符串,以便将其作为不同的命令和参数传递到docker run脚本内部?

采纳答案by larsks

Start with the syntax of the docker runcommand, which is:

docker run命令的语法开始,即:

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

This means if you run:

这意味着如果你运行:

DOCKER_COMMAND='bash -c "(cd build && make)"'
docker run --rm -it myImage "$DOCKER_COMMAND"

You are passing the entirety of the $DOCKER_COMMANDvariable as the COMMAND. You are asking Docker to find a file matching the name bash -c "(cd build && make)", so it should be no surprise that it fails. It doesn't have anything to do with "docker run doesn't understand the substitution". This is all related to the way your shell parses command lines before executing them.

您将整个$DOCKER_COMMAND变量作为COMMAND. 您要求 Docker 查找与 name 匹配的文件bash -c "(cd build && make)",因此它失败也就不足为奇了。它与“docker run 不理解替换”没有任何关系。这都与您的 shell 在执行命令行之前解析命令行的方式有关。

When you remove the quotes around $DOCKER_COMMAND, you end up calling it like this (I'm putting each argument on a separate line to make it obvious):

当您删除 周围的引号时$DOCKER_COMMAND,您最终会像这样调用它(我将每个参数放在单独的一行中以使其显而易见):

docker
run
--rm
-it
myImage
bash
-c
"(cd
build
&&
make)"

And that's not going to work, because bash is going to try to run the script "(cd, which should make obvious the reason for the unexpected EOF while looking for matching"'error. Bash's-c` option only takes a single argument, but because of the way shell expansion works it's getting 4.

这行不通,因为 bash 将尝试运行脚本"(cd,这应该很明显unexpected EOF while looking for matching“' error. Bash's-c` 选项只接受一个参数的原因,但由于 shell 扩展的工作方式,它得到了 4。

You could do it this way:

你可以这样做:

DOCKER_COMMAND='cd build && make'
docker run --rm -it myImage bash -c "$DOCKER_COMMAND"

(I've removed the parentheses around your command because they don't do anything the way you're using them.)

(我已经删除了您命令周围的括号,因为它们不会像您使用它们那样做任何事情。)

This way, you're calling docker runwith a command of bash, and you're giving bash's -coption a single argument (the contents of the $DOCKER_COMMANDvariable).

这样,您docker run使用 的命令进行调用bash,并且为 bash 的-c选项提供了一个参数($DOCKER_COMMAND变量的内容)。