我想完全终止/退出一个错误的bash shell脚本,但使用一个函数error
,让我在终止之前显示一个debugging输出。 现在我遇到这样的问题:如果通过反引号或$()
捕获函数的输出,错误函数中的exit 1
语句将不会终止shell脚本。
这是我的示例脚本:
#!/bin/bash function error () { echo "An error has occured: $1" exit 1 } function do_sth () { if [ $1 -eq 0 ]; then error "First param must be greater than 0!" else echo "OK!" fi } RESULT=`do_sth 0` echo "This line should never be printed"
我怎样才能立即终止在error()
函数中的脚本?
命令替换的问题是,一个子shell开始执行do_sth
。 exit 1
然后终止这个子shell而不是主bash。
你可以通过追加|| exit $?
来解决这个问题 || exit $?
,从命令替换退出代码退出
RESULT=`do_sth 0` || exit $?
如果要显示错误消息,请将其重定向到stderr
echo "An error has occured: $1" >&2
RESULT=`do_sth 0` || exit $?
然后回显“发生错误:$ 1”>&2
没有办法避免这样一个事实,即subshell不能直接使父对象终止:父对象必须计算从subshell返回的值。 一个常见的技术是陷阱出口,并在陷阱函数中输出错误信息。 由于您在子外壳中生成错误消息,因此您不能简单地将消息分配给变量,否则可能会这样做,但可以使用文件系统。 请注意,这个想法是非常愚蠢的,只是把错误信息写到stderr就简单多了。 这就是它的原因,这就是为什么它是由儿童继承。 就像是:
#!/bin/sh trap final 0 2 15 # Create a temporary file to store error messages. This is a terrible # idea: it would be much better to simply write error messages to stderr, # but this code is attempting to demonstrate the technique of having the # parent print the message. Perhaps it would do better to serve as an example # of why reporting your children's mistakes is a bad idea. The children # should be responsible for reporting their own errors. Doing so is easy, # since they inherit file descriptor 2 from their parent. errmsg=$( mktemp xxxxx ) final() { test "$?" = 0 || cat $errmsg rm -f $errmsg } >&2 # Must emphasize one more time that this is a silly idea. The error # function ought to be writing to stderr: eg echo "error: $*" >&2 error() { echo "error: $*" > $errmsg; exit 1; } do_sth() { if test "$1" -eq 0; then error "First param must be greater than 0!" else echo "OK!" fi } result=$( do_sth 0 ) || exit 1 echo not printed
看起来(聪明的)答案是由@FatalError在另一个问题的答案, 在这里
这应该工作…
#!/bin/bash trap "exit 1" 50 #exit process after receiving signal 50. function myerror () { echo "An error has occured: $1" >&2 } function do_sth () { if [ $1 -eq 0 ]; then myerror "First param must be greater than 0!" kill -50 $(ps --pid $$ -opid=) #uncommon signal 50 is used. else echo "OK!" fi } RESULT=`do_sth 1` echo $RESULT RESULT=`do_sth 0` echo $RESULT echo "This line should never be printed"