Linux:运行多个命令而不会丢失单个返回代码?



我读了这个问题,但我的问题是我有"很多"命令要运行;我需要一个适用于系统调用的解决方案。

我们有一个退出任务,它基本上在我们的JVM中触发了许多"清理"活动。我正在处理的部分必须调用某个脚本,不是一次,而是n次!

Java 端的当前实现创建了nProcessBuilder对象;每个对象都运行一个简单的bash script.sh parm...每次运行时parm都不同。

现在我想将 Java 端更改为仅使用ProcessBuilder进行一次系统调用(而不是n)。

我可以使用以下命令:

bash script.sh parm1 ; bash script.sh parm2 ; ... ; bash script.sh parmN

现在的问题是:如果其中一个运行失败......我希望所有其他跑步仍然进行;但我想最终得到一个"错误"的返回代码。

有没有一种简单、优雅的方法来实现这一点,一种适用于来自系统调用的命令字符串的方法?

您可以随时在子外壳中构建返回代码,然后在最后使用算术计算检查它们。 例如,在我的测试系统(cygwin)上,在bash提示符下:

$  ( r=; echo "foo" ; r=$r$?; echo "bar" ; r=$r$? ; echo "baz" ; r=$r$? ; (($r==0)) )
foo
bar
baz
$ echo $?
0          <--- all the commands in the subshell worked OK, so the status is OK

VVVV make this echo fail
$ ( r=; echo "foo" ; r=$r$?; echo "bar" 1>&- ; r=$r$? ; echo "baz" ; r=$r$? ; (($r==0)) )
foo
-bash: echo: write error: Bad file descriptor
baz
$ echo $?
1          <--- failure code, but all the commands in the subshell still ran.

所以,在你的情况下,

(r=; bash script.sh parm1 ; r=$r$?; bash script.sh parm2 ; r=$r$?; ... ; bash script.sh parmN r=$r$?; (($r==0)) )

您还可以使用存储返回代码的函数s使其稍短:

$ (r=;s(){ r=$r$?;}; echo "foo" ; s; echo "bar" 1>&-; s; echo "baz" ; s; (($r==0)) )
foo
-bash: echo: write error: Bad file descriptor
baz
$ echo $?
1

s(){ r=$r$?;}定义了一个将更新r的函数s。 然后,可以在每个命令之后运行ss定义中的空格和分号是必需的。

发生了什么事情?

  • r=r初始化为空字符串。 这将在我们前进的过程中保持我们的返回值。
  • 在每个命令之后,r=$r$?将该命令的退出状态附加到r上。r中没有空格,通过构造,所以我省略了引号以简洁。 有关负返回值的说明,请参阅下文。
  • 最后,如果r计算结果为0,则(($r==0))成功。 因此,如果所有命令都成功,r将被000...0,等于0
  • 子外壳的退出状态
  • 是其最后一个命令的退出状态,此处为(($r==0))测试。 因此,如果r全为零,则子外壳将报告成功。 否则,子外壳将报告失败($?==1)。

负退出值

如果子外壳中的某些程序可能具有负退出值,这可能仍然有效。 例如,0-255100255是不等于零的有效表达式。 但是,如果你有两个命令,第一个以127退出,第二个以-127退出,r将是127-127,即零。

若要避免此问题,请将每个r=$r$?替换为r=$r$((! ! $?))。 双重逻辑否定$((! ! $?))0转换为0,将任何其他值(正值或负值)转换为1。 然后r将只包含01值,因此(($r==0))测试是正确的。 (每个!后都需要空格,因此 bash 不会认为您正在尝试引用您的命令历史记录。

所有退出代码的二进制 OR-ing 将为零 (0) "if"和"仅当"所有退出代码为零 (0)。

您可以使用以下简单的算术表达式获取正在运行的退出代码:

excode=((excode | $?))

要运行所有参数,您可以使用脚本("callcmd"),如下所示:

#!/bin/bash
excode=0
for    i
do     cmd "$i"
excode=((excode | $?))
done
echo "The final exit code is $excode"
# if [[ $excode -ne 0 ]]; exit 1; fi     # An alternative exit solution.

其中,这个脚本("callcmd")从java调用为:

callcmd parm1 parm2 parm3 … parmi … parmN

每个命令的输出在通常的标准输出中可用,错误字符串(如果有的话)也将在 stderr 中可用(但所有字符串都将连接起来,因此命令"cmd"应识别哪个参数发出错误)。

r=0; for parm in parm1 parm2 ... parmN; do
bash script.sh "$parm" || r=1
done
exit "$r" 

你可以这样做

bash script.sh parm1 || echo "FAILED" > some.log ; bash script.sh parm2 || echo "FAILED" > some.log; ... ; bash script.sh parmN|| echo "FAILED" > some.log然后检查是否有一些.log文件。

|| - 这是简单的 bash 逻辑或(如果前一个的退出状态不为零,则执行)

最新更新