运行 容器中的原始命令 shell VS 命令在 shell 中使用 /bin/bash -ac,没有给出相同的结果
Running raw command in container shell VS command using /bin/bash -ac in shell, not giving the same result
当做 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 "[...]"
如果你运行
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}'\''
将单引号转换为单引号字符串。
$() 和 $var inside double quota 在执行命令之前解析。
所以 $file 不会在 new bash 内解析,而是在将字符串发送到 bash 之前解析。所以我相信 $file 在这种情况下会是空的。
当做 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 "[...]"
如果你运行
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}'\''
将单引号转换为单引号字符串。
$() 和 $var inside double quota 在执行命令之前解析。 所以 $file 不会在 new bash 内解析,而是在将字符串发送到 bash 之前解析。所以我相信 $file 在这种情况下会是空的。