如何从函数中有效地中止 Bash 脚本的执行

我在 Bash 函数中使用了“ exit 1”语句来终止整个脚本,它工作得很好:

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

但后来我意识到,它不能完成工作,当被叫做:

res=$(func)

我知道我创建了一个子 shell,“ exit 1”中止了这个子 shell,而不是主要的子 shell; 有没有一种方法可以编写一个中止整个执行的函数,不管它是如何调用的?

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

61031 次浏览

You can use set -e which exits if a command exits with a non-zero status:

set -e
func
set +e

Or grab the return value:

(func) || exit $?

A child process can't force the parent process to close implicitly. You need to use some kind of signaling mechanism. Options might include a special return value, or perhaps sending some signal with kill, something like

function child() {
local parent_pid="$1"
local other="$2"
...
if [[ $failed ]]; then
kill -QUIT "$parent_pid"
fi
}

But is there a way to write a function which aborts the whole execution, no matter how it is called?

No.

I just need to get the real return value (echoed by the function).

You can

res=$(func)
echo $?

What you could do, is register the top level shell for the TERM signal to exit, and then send a TERM to the top level 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"

So, your function sends a TERM signal back to the top level shell, which is caught and handled using the provided command, in this case, "exit 1".

I guess better is

#!/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"

If you just need top be able to bomb out of your scripts from within a function, you can do:

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

then elsewhere, within your functions, instead of using "exit", use "die".