为什么bash eval在后台命令失败时返回零?

时间:2015-10-14 21:34:44

标签: bash eval

编辑这篇文章,原文位于"谢谢!"

下方
command='a.out arg1 arg2 &'
eval ${command}
if [ $? -ne 0 ]; then
   printf "Command \'${command}\' failed\n"
   exit 1
fi
wait

这是一个演示问题的测试脚本,我过于简单了 在原帖中。注意第2行中的&符号和wait命令。 这些更忠实地代表了我的剧本。如果重要,那么&符号 有时在那里,有时不在,它的存在是由用户决定的 - 指定是否为后台长算术的指定标志 计算。而且,如果它很重要,我实际上背景很多 (十二)个过程,即${command[0..11]}。我想要脚本死了,如果有的话 失败。我用'等待'同步所有进程的成功返回。 快乐(有点)使用另一种方法,但这几乎有效。

&符号(用于背景)似乎会导致问题。 当${command}省略&符时,脚本按预期运行: 找不到可执行文件a.out,发出了针对该效果的投诉, 和$?非零,因此主机脚本退出。当${command}包含时 &符号,同样的投诉是发出但是$?是零,所以 脚本继续执行。我希望脚本能够立即死掉 a.out失败但是如何从a获得非零返回值 后台程序?

谢谢!

(原帖):

我有一个使用

形式命令的bash脚本
eval ${command}
if [ $? -ne 0 ]; then
   printf "Command ${command} failed"
   exit 1
fi

其中$ {command}是一串单词,例如" a.out arg1 ... argn"。 问题是来自eval的返回码(即$?)总是如此 即使${command}失败,也为零。删除" eval"从上面 snippet允许返回正确的返回码($?) 停止剧本。我需要将我的命令字符串保存在变量中 (${command})以便在其他地方操纵它,并简单地运行 没有评估的${command}由于其他原因而无法正常工作。我怎么抓住 使用eval时正确的返回码?

谢谢! 查理

2 个答案:

答案 0 :(得分:5)

  

&符号(用于背景)似乎会导致问题。

这是正确的。

在命令完成之前,shell无法知道命令的退出代码。当您在后台放置命令时,shell 不会等待完成。因此,它无法知道后台命令的(未来)返回状态。

man bash中记录了这一点:

  

如果命令由控制操作员&,shell终止   在子shell中在后台执行命令。外壳确实如此   不要等待命令完成,返回状态为0。

换句话说,在后台输入命令后的返回码始终为0,因为shell无法预测尚未完成的命令的未来返回码。

如果要在后台查找命令的返回状态,则需要使用wait命令。

实施例

命令false始终将返回状态设置为1:

$ false ; echo status=$?
status=1

但请注意,如果我们背景会发生什么:

$ false & echo status=$?
[1] 4051
status=0

状态为0,因为命令放在后台,shell无法预测其未来的退出代码。如果我们等一会儿,我们会看到:

$ 
[1]+  Exit 1                  false

在这里,shell正在通知我们完成了背景任务并且它的返回状态正如它应该的那样:1。

在上文中,我们没有使用eval。如果我们这样做,没有任何改变:

$ eval 'false &' ; echo status=$?
[1] 4094
status=0
$ 
[1]+  Exit 1                  false

如果您确实需要后台命令的返回状态,请使用wait。例如,这显示了如何捕获false的返回状态:

$ false & wait $!; echo status=$?
[1] 4613
[1]+  Exit 1                  false
status=1

答案 1 :(得分:1)

从我系统的手册页:

eval [arg ...] args被读取并连接成一个命令。然后shell读取并执行此命令,并将其退出状态作为eval的值返回。如果没有args或只有null参数,则eval返回0.

如果你的系统文档是相同的,那么,很可能,无论你运行什么命令都是问题,即' a.out'正在回归' 0'在退出而不是非零值。添加适当的退出返回代码'你编译的程序。

你也可以尝试使用$()来运行'你的二进制文件而不是评估'它......,即

STATUS = $(a.out var var var)

只有一个命令'在流中,那么$的值是多少?是退出代码&#39 ;;否则,$?是多命令管道中最后一个命令的返回码' ...

:)
戴尔