如果命令失败,请不要中断脚本,而是收集退出代码

时间:2016-11-11 11:54:23

标签: linux bash

我需要在设置了set -e的脚本中执行命令。此命令是通用脚本流的一个例外,因为它可能会失败并且不会很关键:脚本可以继续。我希望该命令能够中断脚本;相反,我想保留退出代码供以后评估。

我提出了以下脚本:

#!/bin/bash

set -e
false && res1=$? || res1=$?
true  && res2=$? || res2=$?
echo $res1
echo $res2

(我的命令将取代falsetrue

这是正确的方法吗?

修改

顺便说一句,这个非常相似的结构根本不起作用:

#!/bin/bash

set -e
false || res1=$? && res1=$?
true  || res2=$? && res2=$?
echo $res1
echo $res2

修改

测试其中一条建议:

#!/bin/bash

set -e
false || { res1=$?; true; }
true  || { res2=$?; true; }
echo $res1
echo $res2

这不起作用。结果是:

1
(empty line)

3 个答案:

答案 0 :(得分:6)

请勿尝试使用&&||来形成三元表达式;它太脆弱了。只需使用if声明。

if cmd; then res=$?; else res=$?; fi

更好(?)但是,您可以将赋值置于条件本身,减少重复,但代价是看似空洞的if语句:

if cmd; res=$?; then :; fi

虽然可以用一个||写得更清楚:

{ cmd; res=$?; } || true

(注意我已经可以互换使用true:; POSIX保证:是内置的shell,但true可能更具可读性。 )

答案 1 :(得分:1)

&&之后放置||没有您想要的效果。例如,

false || echo true && echo false

将打印true和false,即无论第一个命令是否成功,都将执行&&之后的任何内容。你可以这样做:

command && res1=$? || res1=$?

在这种情况下,如果command成功,第三个不会被执行,如果失败,第二个不会被执行。

修改

提到chepnar时,&&||的使用并非完全证明。这种行为无法保证。

答案 2 :(得分:0)

不是两次捕获相同的退出代码,为什么不关闭-e,捕获退出状态并再次启用-e,如下所示:

#!/bin/bash
set -e

set +e          # turn off exit on error
false; res1=$?  # run command1 and capture exit status1
true; res2=$?   # run command2 and capture exit status2
set -e          # turn on exit on error

echo $res1
echo $res2