【问题标题】:Including $@ to pass on all command line arguments when a shell script invokes itself with bash -c当 shell 脚本使用 bash -c 调用自身时,包括 $@ 以传递所有命令行参数
【发布时间】:2020-11-27 08:07:51
【问题描述】:

我需要一个 bash 脚本来调用自身(实际上是在不同的上下文中,在 Docker 容器内),我正在使用 bash -c 命令来执行此操作。但是,即使在这里阅读了很多相关问题之后,我仍在努力解决如何传递所有命令行变量。这是一个示例脚本:

#!/bin/bash
# If not in the right context, invoke script in right context and exit
if [ -z ${NESTED+x} ]; then
  NESTED=true bash -c "./test.sh $@"
  exit
fi

echo "$1"
echo "$2"
echo "$3"

如果我将它保存为 test.sh 并使用 ./test.sh 1 2 "3 4" 调用它,我希望看到这些参数被回显,但只有第一个输出。

如果我使用 set -x,它会显示 bash 插入了一些意外的引用,因此调用变为 NESTED=true bash -c './test2.sh 1' 2 3 4。这解释了输出,但我无法找出正确的方法。

【问题讨论】:

  • 这个mywiki.wooledge.org/BashFAQ/050 应该会给你一些见解。
  • 我想我在问这个问题之前简化了太多代码,因为我实际上是在尝试将命令传递给 docker exec。从菲利普那里得到答案很有用,基本上确认这不是一种可能的方法,但是(鉴于否决票)我应该编辑问题以引入 Docker 角度以使其更有用吗?

标签: bash shell arguments quoting


【解决方案1】:

不应使用bash -c,因为它无法轻松处理"3 4"

#!/bin/bash
# If not in the right context, invoke script in right context and exit
if [ -z ${NESTED+x} ]; then
  NESTED=true ./test.sh "$@"
  exit
fi

echo "$1"
echo "$2"
echo "$3"

【讨论】:

  • 谢谢。不幸的是,我在这里实际上想要做的是调用 docker exec,我不知道是否有办法解决这个问题..
  • Docker 文档说“COMMAND 应该是一个可执行文件,链接或引用的命令将不起作用。例如: docker exec -ti my_container "echo a && echo b" 不起作用,但 docker exec - ti my_container sh -c "echo a && echo b" will."
  • 如果您发布您的 Dockerfile 和运行容器的命令,我们可能会找到解决方案。
  • 我最终接受了在 Bash 中无法以这种方式使用 $@,因此我在上面添加了参数解析,脚本将调用自身并分别传递预期的参数。