我读过this question,但我的问题是我有“大量”命令可以运行;我需要一个适用于系统调用的解决方案。
我们有一个退出任务,它基本上会在我们的JVM中触发很多“清理”活动。我正在处理的部分必须调用某个脚本,而不是一次,但 n 次!
Java端的当前实现创建 n ProcessBuilder
个对象;并且每个运行一个简单的bash script.sh parm
...其中parm
在每次运行时都不同。
现在我想将Java端更改为仅使用ProcessBuilder
进行一次系统调用(而不是 n )。
我可以使用以下命令:
bash script.sh parm1 ; bash script.sh parm2 ; ... ; bash script.sh parmN
现在问题是:如果其中一次运行失败......我希望所有其他运行仍然发生;但我想最终得到一个“坏”的返回码。
是否有一种简单,优雅的方法来实现这一点,一种使用来自系统调用的命令字符串?
答案 0 :(得分:1)
您可以随时在子shell中构建返回码,然后使用算术评估在最后检查它们。例如,在我的测试系统(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$?;}
定义了一个更新s
的函数r
。然后可以在每个命令之后运行s
。 s
定义中的空格和分号是必需的。
r=
将r
初始化为空字符串。这将保留我们的返回值。r=$r$?
将该命令的退出状态添加到r
。 r
中没有空格,通过构造,所以我为了简洁而省略了引号。请参阅下文,了解有关负回报值的说明。(($r==0))
评估为r
,则最后0
成功。因此,如果所有命令都成功,r
将为000
... 0
,等于0
。(($r==0))
测试。因此,如果r
全部为零,则子shell将报告成功。如果没有,子shell将报告失败($?==1
)。如果子shell中的某些程序可能具有负退出值,则这可能仍然有效。例如,0-255100255
是一个不等于零的有效表达式。但是,如果您有两个命令,第一个退出127
,第二个退出-127
,r
将为127-127
,为零。
要避免此问题,请将每个r=$r$?
替换为r=$r$((! ! $?))
。双重逻辑否定$((! ! $?))
将0
转换为0
,将任何其他值(正面或负面)转换为1
。然后r
将只包含0
和1
值,因此(($r==0))
测试将是正确的。 (每次!
之后你确实需要空格,所以bash并不认为你是在试图引用你的命令历史。)
答案 1 :(得分:0)
所有退出代码的二进制OR-ing将为零(0)&#34;如果&#34;和&#34;只有&#34;所有退出代码均为零(0)。
您可以使用这个简单的算术表达式获得正在运行的退出代码:
excode=((excode | $?))
要运行所有参数,您可以使用脚本(&#34; callcmd&#34;),如:
#!/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.
从java调用此脚本(&#34; callcmd&#34;):
callcmd parm1 parm2 parm3 … parmi … parmN
每个命令的输出在通常的标准输出中可用,并且错误字符串(如果有的话)也可以在stderr中使用(但是所有命令都将被连接,因此命令&#34; cmd&#34;应该识别parm正在发出错误。)
答案 2 :(得分:0)
r=0; for parm in parm1 parm2 ... parmN; do
bash script.sh "$parm" || r=1
done
exit "$r"
答案 3 :(得分:-1)
你可以这样做
bash script.sh parm1 || echo "FAILED" > some.log ; bash script.sh parm2 || echo "FAILED" > some.log; ... ; bash script.sh parmN|| echo "FAILED" > some.log
然后检查是否有some.log文件。
|| - 它是简单的bash逻辑或(如果前一个的退出状态为非零则执行)