首页 > 解决方案 > 在 shell 中使用 /bin/bash -ac 在容器 shell 中运行原始命令 VS 命令,但结果不一样

问题描述

做的时候docker exec -it [container_id] /bin/bash

我在下面运行了以下内容:
请假设文件夹test/data存在。

root@6f200d5b9691: for file in $(aws s3 ls s3://foo-bucket | awk '{print $NF}') ; do aws s3 cp foo-bucket/${file} test/data && tar -xzf test/data/${file} -C test/data/ ; done

为此,我得到了相关路径下的所有文件并解压!

但是,当以这种方式通过 shell 执行完全相同的操作时:
root@6f200d5b9691: /bin/bash -ac "for file in $(aws s3 ls s3://foo-bucket | awk '{print $NF}') ; do aws s3 cp foo-bucket/${file} test/data && tar -xzf test/data/${file} -C test/data/ ; done"

我收到奇怪的错误,例如:
/bin/bash: -c: line 1: syntax error near unexpected token foo1.tar.gz' /bin/bash: -c: line 1: foo1.tar.gz ; do aws s3 cp s3://foo-bucket/foo1.tar.gz 'test/data' && tar -xzf 'test/data/foo1.tar.gz' -C 'test/data/' ; done'

知道为什么会这样吗?我在做什么错?

运行 via 的第二个选项/bin/bash -ac "[commands here]"很重要,因为我想在 via 命令中使用它,例如:
docker-compose run [service_name] /bin/bash -ac "[...]"

标签: bashdockermakefiledocker-composeaws-cli

解决方案


如果你跑

bash -c "file=foo; echo $file"

什么都没有打印,因为在看到它$file之前被扩展(什么都没有) 。bash -c

解决方案是使用单引号:

bash -c 'file=foo; echo "$file"'

现在,bash -c可以看到未修改的整个论点。

对于您的情况,这意味着

bash -ac 'for file in $(aws s3 ls s3://foo-bucket | awk "{print \$NF}"); do
    aws s3 cp foo-bucket/"$file" test/data \
        && tar -xzf test/data/"$file" -C test/data/
done'

其中整个字符串是单引号的。这允许正确引用$file; 对于 awk 命令,我们必须转义$NF,因为我们使用双引号。一个替代方案是

awk '\''{print $NF}'\''

将单引号转换为单引号字符串。


推荐阅读