Execute for loop in docker container
Solution 1
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.
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).
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'
Solution 2
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 :
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 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.
DenCowboy
Updated on June 27, 2022Comments
-
DenCowboy almost 2 years
I use a docker container to perform a 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.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 ...
-
DenCowboy about 7 yearsThanks, But now I get something like: done\": executable file not found in $PATH" (with the single quotes). Without the single quotes and using your $() it's just the same error as before
-
Aaron about 7 years@DenCowboy
$()
and backticks have the same effect, I just switched to the more modern$()
because it has a few advantages such as the possibility of nesting, but it shouldn't matter in your case. Could you maybe edit the exact error message in your question? Right now it looks like you've got an extra double quote just after thedone
keyword which makes it misunderstood, but I don't see what could cause this -
DenCowboy about 7 years
... tutum/curl /bin/bash -c 'for i...
this worked. You can edit if you want. found it thanks to your answer -
Aaron about 7 yearsHmm I'd rather not edit my answer without understanding why it worked. I'll try to understand what went on here, but if I don't edit in a few hours you might as well just upvote my answer, post your own and accept it.
-
Aaron about 7 yearsLooks like
docker run
uses/bin/sh -c
to execute the commands it's provided, so either you made a typo when you first tried with just the command, something adds an extra"
, your url contains a quote, or the command is valid inbash
but not insh
. Also/bin/sh -c 'for i in
seq 1 10; do echo $i;done'
works just fine, so I doubt the last one