bash的函数如果有返回值,并要赋值给一个变量,跟普通的命令调用没有差异,都是: v=$(func)
的方式。需要注意的是,这里执行了fork
操作,如果函数里有调用exit
的话,只是让子进程退出,当前进程并不会退出。如果想要让当前进程也退出,可以使用set -e
或在函数调用结束的时候再判断一次,比如:
v=$(func) || exit $?
如果函数调用失败,当前进程也退出。
今天遇到一个跟这个相关的陷阱,但并不是fork
的问题,而是bash语法解析的问题,先看看我当时的写法,脚本简化后:
$ cat a.sh
#!/bin/bash
foo() {
echo "error" && exit 1
}
bar() {
local r=$( foo ) || exit $?
echo $r # 执行了这里
}
bar
如上,函数bar以fork的方式调用foo,我们预期是foo返回值不为0时,bar函数也退出。所以上面bar函数里最后的echo $r
不应该被执行到。但实际运行的时候发现这段代码确实可以执行到bar函数的最后一行。
后来,去掉了local
修饰符,执行符合预期了:
bar() {
r=$( foo ) || exit $?
echo $r # 不会执行到这里
}
看来是 r=$( foo ) || exit $?
里的逻辑或||
被解析器作为等号后边两个命令的逻辑运算;而前边加了local
修饰符之后,逻辑或||
被当成表达式local r=$(foo)
与 命令 exit
之间的逻辑运算。