简体   繁体   English

如何转义通过 bash -c 传递给 bash 的命令?

[英]How can I escape a command passed to bash via bash -c?

I would like to run the following command via docker -c :我想通过docker -c运行以下命令:

for line in `docker ps | awk '{print $1}' | grep -v CONTAINER`; do docker ps | grep $line | awk '{printf $NF" "}' && echo $(( `cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes` / 1024 / 1024 ))MB ; done

How do I have to escape the command when passing it via -c ?通过-c传递命令时如何转义命令? What symbols do I have to escape?我必须逃避什么符号?

I tried various versions, including this one, which gives me the error unexpected EOF while looking for matching "我尝试了各种版本,包括这个版本,它unexpected EOF while looking for matching "给了我unexpected EOF while looking for matching "错误

bash -c 'for line in \`docker ps | awk \'{print $1}\' | grep -v CONTAINER\`\; do docker ps | grep $line | awk \'{printf $NF\\" \\"}\' && echo $(( \`cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes\` / 1024 / 1024 ))MB \; done

Sidenote: The command gives you the memory consumption for each docker container.旁注:该命令为您提供每个 docker 容器的内存消耗。

I am guessing you are trying to divide the number of bytes.我猜你正试图划分字节数。 In order to do arithmetic calculations you need to use expr .为了进行算术计算,您需要使用expr Try this:尝试这个:

for line in `docker ps | awk '{print $1}' | grep -v CONTAINER`; do docker ps | grep $line | awk '{printf $NF" "}' && echo $(expr $( cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes) / 1024 / 1024 )MB ; done

Found the solution:找到了解决办法:

bash -c 'for line in $(docker ps | awk '"'"'{print $1}'"'"' | grep -v CONTAINER); do docker ps | grep $line | awk '"'"'{printf $NF" "}'"'"' && echo $(( $(cat /sys/fs/cgroup/memory/docker/$line*/memory.usage_in_bytes) / 1024 / 1024 ))MB ; done'

Can someone explain it to me?有人可以向我解释一下吗?

IIUC, it's a good use case for Bash printf %q specifier. IIUC,这是 Bash printf %q说明符的一个很好的用例。 Save a line to a file, say /tmp/DOCKER-COMMAND and then format it with printf %q :将一行保存到文件中,例如 /tmp/DOCKER-COMMAND,然后使用printf %q对其进行printf %q

$ printf "%q\n" "$(< /tmp/DOCKER-COMMAND)"
for\ line\ in\ \`docker\ ps\ \|\ awk\ \'\{print\ \$1\}\'\ \|\ grep\ -v\ CONTAINER\`\;\ do\ docker\ ps\ \|\ grep\ \$line\ \|\ awk\ \'\{printf\ \$NF\"\ \"\}\'\ \&\&\ echo\ \$\(\(\ \`cat\ /sys/fs/cgroup/memory/docker/\$line\*/memory.usage_in_bytes\`\ /\ 1024\ /\ 1024\ \)\)MB\ \;\ done

You can copy the output line and paste it literally to bash -c :您可以复制输出行并将其逐字粘贴到bash -c

$ bash -c for\ line\ in\ \`docker\ ps\ \|\ awk\ \'\{print\ \$1\}\'\ \|\ grep\ -v\ CONTAINER\`\;\ do\ docker\ ps\ \|\ grep\ \$line\ \|\ awk\ \'\{printf\ \$NF\"\ \"\}\'\ \&\&\ echo\ \$\(\(\ \`cat\ /sys/fs/cgroup/memory/docker/\$line\*/memory.usage_in_bytes\`\ /\ 1024\ /\ 1024\ \)\)MB\ \;\ done
fervent_gates 2MB
youthful_wozniak 3MB

Does it need to fit in a single line?它需要放在一行中吗? Using a quoted heredoc gets you out of most quoting trouble:使用引用的 heredoc 可以让您摆脱大多数引用问题:

bash <<'END_BASH'
    docker ps | {
        read header
        while read -ra fields; do 
            mem=$(< /sys/fs/cgroup/memory/docker/"${fields[0]}"*/memory.usage_in_bytes)
            printf "%s %dMB\n" "${fields[-1]}" $((mem / 1024 / 1024))
        done
    }
END_BASH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM