如果任何命令返回非零值,则中止shell脚本?

时间:2009-05-04 18:55:50

标签: linux bash unix shell

我有一个Bash shell脚本,可以调用许多命令。 如果任何命令返回非零值,我想让shell脚本自动退出,返回值为1。

如果没有明确检查每个命令的结果,这是否可行?

e.g。

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi

9 个答案:

答案 0 :(得分:660)

将其添加到脚本的开头:

set -e

如果一个简单的命令以非零退出值退出,这将导致shell立即退出。一个简单的命令是任何命令都不属于if,while或者直到测试,或者是&&和/或或||列表。

有关详细信息,请参阅“set”内部命令中的bash(1) man page

我个人用“set -e”启动几乎所有的shell脚本。当一个脚本在中间出现故障并且打破其余脚本的假设时,让脚本顽固地继续下去真的很烦人。

答案 1 :(得分:180)

添加到接受的答案:

请记住set -e有时是不够的,特别是如果你有管道。

例如,假设您有此脚本

#!/bin/bash
set -e 
./configure  > configure.log
make

...按预期工作:configure中的错误会中止执行。

明天你会做出一个看似微不足道的变化:

#!/bin/bash
set -e 
./configure  | tee configure.log
make

......现在它不起作用。这解释为here,并提供了一种解决方法(仅限Bash):

#!/bin/bash
set -e 
set -o pipefail

./configure  | tee configure.log
make

答案 2 :(得分:74)

您的示例中的if语句是不必要的。就这样做:

dosomething1 || exit 1

如果您接受Ville Laurikari的建议并使用set -e,那么对于某些命令,您可能需要使用此命令:

dosomething || true

即使命令失败,|| true也会使命令管道具有true返回值,因此-e选项不会终止该脚本。

答案 3 :(得分:26)

如果你需要在退出时进行清理,你也可以使用'陷阱'和伪信号ERR。这与捕获INT或任何其他信号的方式相同;如果任何命令以非零值退出,则bash抛出ERR:

# Create the trap with   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah

或者,特别是如果你使用“set -e”,你可以捕获EXIT;当脚本因任何原因退出时,您的陷阱将被执行,包括正常结束,中断,由-e选项引起的退出等。

答案 4 :(得分:12)

在顶部使用-eset -e运行它。

另请查看set -u

答案 5 :(得分:10)

很少需要$?变量。伪成语command; if [ $? -eq 0 ]; then X; fi应始终写为if command; then X; fi

需要$?的情况是需要针对多个值进行检查的时间:

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

或当$?需要重复使用或以其他方式操纵时:

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi

答案 6 :(得分:3)

这样的表达式
dosomething1 && dosomething2 && dosomething3
当其中一个命令返回非零值时,

将停止处理。例如,以下命令将永远不会打印“done”:

cat nosuchfile && echo "done"
echo $?
1

答案 7 :(得分:3)

#!/bin/bash -e

应该足够了。

答案 8 :(得分:-2)

只是投入另一个作为参考,因为Mark Edgars输入还有一个问题,这是一个额外的例子,并涉及整个主题:

[[ `cmd` ]] && echo success_else_silence

与有人展示的cmd || exit errcode相同。

例如。我想确保在挂载时卸载分区:

[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1