在外壳中使用/ bin / bash -ac在容器外壳VS命令中运行raw命令,但结果不一样

时间:2020-04-12 21:48:11

标签: bash docker makefile docker-compose aws-cli

进行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'

知道为什么会发生吗? 我在做什么错了?

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

2 个答案:

答案 0 :(得分:3)

如果您运行

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

没有打印任何内容,因为$filebash -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}'\''

将单引号包含在单引号中。

答案 1 :(得分:0)

在执行命令之前,双配额内的

$()和$ var解析。 因此$ file不会在新的bash中解析,而是在将字符串发送到bash之前解析。因此,我相信$ file在这种情况下将为空。