容器内与宿主机执行带awk的Bash命令结果不一致问题
问题与解决方法
问题
容器内执行以下命令可正常输出进程PID列表:
root@foo:/# for pid in `ps -ax|awk '{print $1}'` ;do echo $pid; done PID 1 17 18 34 1792 2952 3623 3649 3650 3651
但在宿主机通过docker exec执行相同命令时,出现语法错误:
[ec2-user@ip-x ~]$ docker exec b1b bash -c "for pid in `ps -ax|awk '{print $1}'` ;do echo $pid; done" bash: -c: line 1: syntax error near unexpected token `1' bash: -c: line 1: `1'
尝试转义$符号后,问题仍未解决:
docker exec b1b bash -c "for pid in `ps -ax|awk \"{print \$1}\"`;do echo $pid; done" bash: -c: line 1: syntax error near unexpected token `1' bash: -c: line 1: ` 1 ? Ss 10:56 /usr/lib/systemd/systemd --system --deserialize 21'
目标是通过docker exec执行命令后,得到与容器内直接执行完全相同的结果。
核心原因
宿主机的Shell会优先解析docker exec命令中双引号内的反引号和未转义的$符号,导致实际传递给容器内Shell的命令已经被宿主机替换成了宿主机本地ps命令的结果,进而引发语法错误。
解决方法
方法一:用单引号包裹bash -c的命令内容
单引号可以阻止宿主机Shell解析内部的特殊字符,让命令原封不动传递给容器内的Shell执行。注意内部的单引号需要用\'转义:
docker exec b1b bash -c 'for pid in `ps -ax|awk '\''{print $1}'\''` ;do echo $pid; done'
或者更推荐使用$()替代反引号(可读性更好):
docker exec b1b bash -c 'for pid in $(ps -ax | awk '\''{print $1}'\''); do echo $pid; done'
方法二:对双引号内的特殊字符全面转义
如果坚持使用双引号,需要对所有宿主机Shell会解析的特殊字符(反引号、$)进行转义:
docker exec b1b bash -c "for pid in \`ps -ax|awk '{print \$1}'\` ;do echo \$pid; done"
执行以上任意一种命令,即可得到和容器内直接执行相同的PID列表输出。
内容的提问来源于stack exchange,提问作者user12548239
相关产品推荐
相关产品推荐

