bash 在 docker 容器中执行 for 循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42509726/
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
Execute for loop in docker container
提问by DenCowboy
I use a docker container to perform a curl
我使用 docker 容器来执行 curl
docker run --rm --network=mynetwork tutum/curl for i in `seq 1 10`; do curl -s http://Url; done
But the output is -bash: syntax error near unexpected token
do'`.
How do I execute this in a proper way. I want to see the output without going inside the container or checking their logs.
但输出是-bash: syntax error near unexpected token
do'`。我如何以正确的方式执行此操作。我想在不进入容器或检查其日志的情况下查看输出。
For example this works:
例如这有效:
docker run --rm -d -it --network=mynetwork tutum/curl /bin/sh
docker exec -it 4e8cb1e8c9fb bash
root@4e8cb1e8c9fb:/# for i in `seq 1 20`; do curl http://Url; done
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
curl: (6) Could not resolve host: url
...
采纳答案by BMitch
As Aaron points to, you need a shell inside the container to parse this line, rather than letting it get parsed by the same shell that parses the docker command. By default docker will pass commands to a /bin/sh
entrypoint if you don't have one defined. And if you try escaping any shell characters on the docker cli, it "helps" you by also escaping them on the /bin/sh
command line which prevents you from passing something like a ;
through and getting it parsed by the shell there or quoting your script and having it parsed by the /bin/sh -c
. If you quote the script without parsing it, you'll find that it looks for an executable with the full string's name.
正如 Aaron 所指出的,您需要在容器内有一个 shell 来解析这一行,而不是让它被解析 docker 命令的同一个 shell 解析。默认情况下,/bin/sh
如果您没有定义入口点,docker 会将命令传递给入口点。如果您尝试在 docker cli 上转义任何 shell 字符,它还会通过在/bin/sh
命令行上转义它们来“帮助”您,这会阻止您传递类似 pass 之类的内容;
并在那里被 shell 解析或引用您的脚本并使用它由/bin/sh -c
. 如果您引用脚本而不对其进行解析,您会发现它查找具有完整字符串名称的可执行文件。
The solution, as you've found, is to run a shell with /bin/sh -c "your script"
as your command. Note that the script you run needs to be a single argument to /bin/sh -c
, anything else will get passed as args to that script (which you can read with $0
, $1
, etc).
正如您所发现的,解决方案是使用/bin/sh -c "your script"
您的命令运行 shell 。请注意,你需要运行的脚本是一个单独的参数/bin/sh -c
,别的都会被当作参数传递给该脚本(你可以读通过$0
,$1
等等)。
The resulting command should look like:
结果命令应如下所示:
docker run --rm --network=mynetwork tutum/curl \
/bin/sh -c 'for i in `seq 1 10`; do curl -s http://Url; done'
回答by Aaron
Your problem happens because the ;
after your for
is parsed by the bash
outside your container as a command separator, so these are the two commands you're executing :
你的问题发生,因为;
你以后for
由解析bash
之外你作为一个命令分隔容器,所以这些都是你执行两个命令:
docker run --rm --network=mynetwork tutum/curl for i in `seq 1 10`
do curl -s http://Url; done
docker run --rm --network=mynetwork tutum/curl for i in `seq 1 10`
do curl -s http://Url; done
The second is invalid, which is what the error you're getting means.
第二个是无效的,这就是你得到的错误意味着什么。
I think you could simply enclose the command you want to pass to docker in single-quotes :
我认为您可以简单地将要传递给 docker 的命令用单引号括起来:
docker run --rm --network=mynetwork tutum/curl 'for i in $(seq 1 10); do curl -s http://Url; done'
The use of single-quotes over double-quotes means that the command won't be expanded in your current shell but rather inside the docker component. It doesn't matter here as the only thing to expand is the seq 1 10
subshell which will obviously produce the same result on both environments.
在双引号上使用单引号意味着该命令不会在您当前的 shell 中展开,而是在 docker 组件中展开。这里无关紧要,因为唯一需要扩展的是seq 1 10
子shell,它显然会在两种环境中产生相同的结果。
回答by GreensterRox
Maybe try wrapping docker call in a bash script and loop?
也许尝试将 docker call 包装在 bash 脚本中并循环?
#!/bin/bash
for i in {1..20}
do
docker run -i -t --entrypoint curl http://Url;
done