如何编写一个 shell 脚本,如果其中一部分失败,该脚本就会退出?例如,如果以下代码片段失败,则脚本应退出。
n=0
until [ $n -ge 5 ]
do
gksu *command* && break
n=$[$n+1]
sleep 3
答案1
一种方法是添加set -e
到脚本的开头。这意味着(来自help set
):
-e Exit immediately if a command exits with a non-zero status.
因此,如果任何命令失败,脚本将退出。
或者,您可以exit
在可能的失败点添加显式语句:
command || exit 1
答案2
您可以使用关键字在任何位置退出脚本exit
。您还可以指定退出代码,以便向其他程序指示您的脚本失败或如何失败,例如exit 1
等等exit 2
。(按照惯例,退出代码 0 表示成功,任何大于 0 的值表示失败;但是,按照惯例,退出127 以上的代码保留用于异常终止(例如通过信号)。
失败时退出的通用结构是
if [ failure condition ]; then
exit n
fi
与合适的failure condition
和n
.但在特定情况下,您可能会采取不同的处理方式。现在,对于您的情况,我解释您的问题,如果五次调用中的任何一个gksu
失败,那么您的意思是退出。一种方法是使用这样的函数
function try_command {
for i in 1 2 3 4 5 ; do
if gksu command ; then
return 0
fi
fi
exit 1
}
然后,通过 调用循环try_command
。
有(更)高级或更复杂的方法来解决您的问题。然而,上面的解决方案比 Stephane 的解决方案更适合初学者。
答案3
attempt=0
until gksu command; do
attempt=$((attempt + 1))
if [ "$attempt" -gt 5 ]; then
exit 1
fi
done
exit
退出脚本,除非在子 shell 中调用它。如果脚本的该部分位于子 shell 中,例如因为它位于管道内(...)
或管道的一部分,那么它只会退出$(...)
那个子壳。
在这种情况下,如果您想要脚本要除了子 shell 之外还退出,那么您需要调用exit
该子 shell 退出。
例如,这里有 2 层嵌套的子 shell:
(
life=hard
output=$(
echo blah
[ "$life" = easy ] || exit 1 # exit subshell
echo blih not run
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
echo not run either
) || exit # if the subshell exits with a non-zero exit status,
# exit as well with the same exit status
如果子 shell 是管道的一部分,事情会变得更加棘手。bash
有一个特殊的$PIPESTATUS
数组,类似于zsh
的$pipestatus
数组,可以在这里为您提供帮助:
{
echo foo
exit 1
echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
exit "$subshell_ret"
fi
答案4
pass_to_functio()
{
echo "command exited with status $1"
}
(
exec <Any Command > &
child_pid=$!
wait $child_pid
pass_to_function $?
)&