I want to execute a docker command on a remote server. The problem is I don't know to escape multiple quotes.
ret=$(ssh root@server "docker exec nginx bash -c 'cat /etc/nginx/nginx.conf | grep 'ServerName' | cut -d '|' -f1'")
I get
bash: -f1: command not found
CodePudding user response:
There's little need to execute so much on the remote host. The file you want to search isn't likely that big: just pipe the entire thing down via ssh
to a local awk
process:
ret=$(ssh root@server "docker exec nginx cat /etc/nginx/nginx.conf" |
awk -F'|' '/ServerName/ {print $1}')
CodePudding user response:
EDIT: Originally the answer suggested to use quote
, but that only works in interactive shells and according to @JohnKugelman it's better to use printf "%q"
. So I have replaced quote
with printf "%q"
Just wrap your parameter string with N calls to "$(printf "%q" ...)"
, for N recursive calls .
ssh root@server "docker exec nginx bash -c 'cat /etc/nginx/nginx.conf | grep ServerName | cut -d | -f1'"
How may recursive calls the above line has? I don't wish to set up docker just for the test, so I may have one of the following wrong:
- ssh - certainly counts
- docker - ??
- ngix - ??
- bash - certainly counts
If there are four, then you need four calls to "$(printf "%q "str")"
, don't forget to add all those "
marks
ssh root@server docker exec nginx bash -c "$(printf "%q" "$(printf "%q" "$(printf "%q" "$(printf "%q" "cat /etc/nginx/nginx.conf | grep ServerName | cut -d | -f1")")")")"
Explanation: ssh
parses the string like bash -c
does, stripping one level of quotes. docker and nginx may also each parse the string (or not). Finally, bash -c
parses whatever the previous levels have parsed, and removes the final level of quotes. exec
does not parse the strings, it simply passes them verbatim to the next level.
Another solution is to put the line, that you want bash to execute, into a script. Then you can simply invoke the script without all this quoting insanity.
#!/bin/bash
< /etc/nginx/nginx.conf grep ServerName | cut -d | -f1
CodePudding user response:
Consider using here-document
:
ret="$(ssh root@server << 'EOF'
docker exec nginx bash -c "grep 'ServerName' /etc/nginx/nginx.conf | cut -d '|' -f1"
EOF
)"
echo "$ret"
Or, simpler as suggested by @MichaelVeksler :
ret="$(ssh root@server docker exec -i nginx bash << 'EOF'
grep 'ServerName' /etc/nginx/nginx.conf | cut -d '|' -f1
EOF
)"
echo "$ret"