![](/img/trans.png)
[英]How to exit from shell script if any of the command in SSH returns non-zero value
[英]Aborting a shell script if any command returns a non-zero value
我有一个调用许多命令的 Bash shell 脚本。
如果任何命令返回非零值,我想让 shell 脚本自动退出,返回值为 1。
如果不明确检查每个命令的结果,这可能吗?
例如,
dosomething1
if [[ $? -ne 0 ]]; then
exit 1
fi
dosomething2
if [[ $? -ne 0 ]]; then
exit 1
fi
将此添加到脚本的开头:
set -e
如果一个简单的命令以非零退出值退出,这将导致 shell 立即退出。 一个简单的命令是不属于 if、while 或 until 测试的一部分,或者不属于 && 或 || 的任何命令列表。
有关更多详细信息,请参阅“set”内部命令上的bash(1) 手册页。
我个人以“set -e”开始几乎所有的 shell 脚本。 当中间出现故障并破坏脚本其余部分的假设时,让脚本顽固地继续下去真的很烦人。
添加到接受的答案:
请记住set -e
有时是不够的,特别是如果您有管道。
例如,假设你有这个脚本
#!/bin/bash
set -e
./configure > configure.log
make
...按预期工作: configure
的错误中止执行。
明天你做一个看似微不足道的改变:
#!/bin/bash
set -e
./configure | tee configure.log
make
......现在它不起作用。 此处对此进行了解释,并提供了一种解决方法(仅限 Bash):
#!/bin/bash set -e set -o pipefail ./configure | tee configure.log make
您示例中的 if 语句是不必要的。 只需这样做:
dosomething1 || exit 1
如果您接受 Ville Laurikari 的建议并使用set -e
那么对于某些命令,您可能需要使用以下命令:
dosomething || true
|| true
即使命令失败, || true
也会使命令管道具有true
返回值,因此-e
选项不会终止脚本。
如果您需要在退出时进行清理,您还可以使用带有伪信号 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 选项引起的退出等。
$?
很少需要变量。 伪习语command; if [ $? -eq 0 ]; then X; fi
command; if [ $? -eq 0 ]; then X; fi
command; if [ $? -eq 0 ]; then X; fi
应该总是写成if command; then X; fi
if command; 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
在顶部使用-e
或set -e
运行它。
也看看set -u
。
出错时,以下脚本将打印 RED 错误消息并退出。
将其放在 bash 脚本的顶部:
# BASH error handling:
# exit on command failure
set -e
# keep track of the last executed command
trap 'LAST_COMMAND=$CURRENT_COMMAND; CURRENT_COMMAND=$BASH_COMMAND' DEBUG
# on error: print the failed command
trap 'ERROR_CODE=$?; FAILED_COMMAND=$LAST_COMMAND; tput setaf 1; echo "ERROR: command \"$FAILED_COMMAND\" failed with exit code $ERROR_CODE"; put sgr0;' ERR INT TERM
#!/bin/bash -e
应该足够了。
像这样的表达
dosomething1 && dosomething2 && dosomething3
当其中一个命令返回非零值时,将停止处理。 例如,以下命令永远不会打印“done”:
cat nosuchfile && echo "done"
echo $?
1
我只是抛出另一个供参考,因为 Mark Edgars 的输入还有一个额外的问题,这里是一个额外的例子,涉及整个主题:
[[ `cmd` ]] && echo success_else_silence
与cmd || exit errcode
相同如某人所示cmd || exit errcode
。
例如,如果已安装,我想确保卸载分区:
[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.