95

我在我的 Bash 函数中使用“exit 1”语句来终止整个脚本,它运行良好:

function func()
{
   echo "Goodbye"
   exit 1
}
echo "Function call will abort"
func
echo "This will never be printed"

但后来我意识到它在调用时不起作用:

res=$(func)

我知道我创建了一个子外壳,并且“退出 1”中止了该子外壳,而不是主外壳....

但是有没有办法编写一个中止整个执行的函数,不管它是如何被调用的?我只需要获取真正的返回值(由函数回显)。

4

6 回答 6

108

可以做的是注册顶级 shellTERM以退出信号,然后将 a 发送TERM到顶级 shell:

#!/bin/bash
trap "exit 1" TERM
export TOP_PID=$$

function func()
{
   echo "Goodbye"
   kill -s TERM $TOP_PID
}

echo "Function call will abort"
echo $(func)
echo "This will never be printed"

因此,您的函数将TERM信号发送回顶级 shell,使用提供的命令(在本例中为"exit 1".

于 2012-03-27T16:54:55.317 回答
46

如果命令以非零状态退出,您可以使用set -ewhich exits :

set -e 
func
set +e

或者获取返回值:

(func) || exit $?
于 2012-03-27T16:30:08.943 回答
2

子进程不能强制父进程隐式关闭。您需要使用某种信号机制。选项可能包括一个特殊的返回值,或者可能使用 发送一些信号kill,例如

function child() {
    local parent_pid="$1"
    local other="$2"
    ...
    if [[ $failed ]]; then
        kill -QUIT "$parent_pid"
    fi
}
于 2012-03-27T16:31:10.303 回答
2

我想更好的是

#!/bin/bash
set -e
trap "exit 1" ERR

myfunc() {
     set -x # OPTIONAL TO SHOW ERROR
     echo "Exit with failure"
     set +x # OPTIONAL
     exit 1
}
echo "BEFORE..."
myvar="$(myfunc)"
echo "AFTER..But not shown"
于 2019-06-19T08:50:04.480 回答
0

但是有没有办法编写一个中止整个执行的函数,不管它是如何被调用的?

不。

我只需要获取真正的返回值(由函数回显)。

你可以

res=$(func)
echo $?
于 2012-03-27T16:34:45.707 回答
0

如果您只需要 top 能够从函数中轰炸您的脚本,您可以执行以下操作:

function die () {
    set -e
    /bin/false
}

然后在其他地方,在你的函数中,而不是使用“exit”,使用“die”。

于 2022-02-23T03:46:16.407 回答