与 `bash -c` 命令混淆 - 不适用于全局变量

Confused with `bash -c` command - does not work with global variables

我有两个 shell 命令,实际上是相同的片段,将它们粘贴到终端时:

这个有效:

while true; do \
sleep 1; \
ping -c 1 'www.google.com'; echo $?; \
if [ $? -eq 0 ]; then break; fi; \
done

这不是:

/bin/bash -c "(while true; do \
sleep 1; \
ping -c 1 'www.google.com'; \
if [ $? -eq 0 ]; then break; fi; \
done); \
exit 0"

第二个命令告诉我退出状态为 130(在 if 执行的行中)即使 ping 执行良好所以退出状态应该为 0。

就像我传递给/bin/bash -c的字符串中的命令没有在全局变量$?中注册最后一个退出值。有什么办法可以实现吗?

提前致谢

bash -c 解释字符串中的命令之前,您的双引号字符串被展开,因此 $? 可能是前一个命令的退出代码。

您可以通过一个示例来了解这一点,我们还使用 -x 标志来查看幕后情况:

$ set -x
$ bash -c "v=5; echo $v"
+ bash -c 'v=3; echo '

您可以看到当执行到该行时没有要回显的 $v 值,因为 $v 在命令被 bash -c 解释之前已经被替换。

进一步到期;要获得与您的问题几乎相同的输出,请执行以下操作:

  1. 运行 cat 没有参数和 ctrl+c 中断。
  2. 运行 bash -c "echo 'hi'; echo $?"

你应该得到 hi130 作为输出,这是你的 sigint'd cat 命令的退出代码。 (请注意,这不是您所期望的 echo "hi" 的出口 0)。


感谢您的命令,您只需换掉引号即可避免此问题:

/bin/bash -c '(while true; do \
sleep 1; \
ping -c 1 "www.google.com"; \
if [ $? -eq 0 ]; then break; fi; \
done); \
exit 0'