bash的set -e和set -o pipefail
2021-10-20 本文已影响0人
CodingCode
- set -e
命令的含义是:若指令传回值不等于0,则立即退出shell。
$ cat t.sh
#!/usr/bin/env bash
set -e
echo "0000"
ls *.notexist
echo "9999"
$ ./t.sh
0000
ls: *.notexist: No such file or directory
$ echo $?
2
在shell脚本t.sh中,如果第一命令ls *.notexist
执行失败了(即返回值不为零),则退出整个t.sh脚本,放气随后的其他所有命令,并且返回第一个失败命令的返回值(2就是ls *.notexist
的返回值)。
- 同时适用于函数返回值
$ cat t.sh
#!/usr/bin/env bash
set -e
function foo() {
return 9
}
echo "0000"
foo
echo "9999"
$ ./t.sh
000
$ echo $?
9
这里9是函数foo()
的返回值。
- 也适用于函数内的命令
$ cat t.sh
#!/usr/bin/env bash
set -e
function foo() {
echo "foo-000"
ls *.notexist
echo "foo-999"
return 9
}
echo "0000"
foo
echo "9999"
$ ./t.sh
0000
foo-000
ls: cannot access *.notexist: No such file or directory
$ echo $?
2
这里2函数内命令ls *.notexist
的返回值。我们看到函数foo()内其他的命令也都没有执行了。
- 和子函数(sub)内的命令
$ cat t.sh
#!/usr/bin/env bash
set -e
function sub() {
echo "sub-000"
ls *.notexist
echo "sub-999"
return 5
}
function foo() {
echo "foo-000"
sub
echo "foo-999"
return 9
}
echo "0000"
foo
echo "9999"
$ ./t.sh
0000
foo-000
sub-000
ls: cannot access *.notexist: No such file or directory
$ echo $?
2
可以看到即使在子函数内的命令执行返回非零值,则整个脚本t.sh就停止执行并返回那个非零值。
- set -o pipefail
前面set -e
的命令有一种例外,即:
$ cat t.sh
#!/usr/bin/env bash
set -e
echo "0000"
ls *.notexist | echo "hehe"
echo "9999"
$ ./t.sh
0000
hehe
ls: cannot access *.notexist: No such file or directory
9999
$ echo $?
0
即使ls *.notexist执行失败了返回非零值,整个脚本并没有停止,而是继续往下执行,并最终返回成功(0)。有些场合这不是我们需要的。
原因是这里使用了pipeline,bash缺省使用pipeline的最后一个命令的返回值作为整条命令的返回值,这里最后一个命令是echo
,它的执行没错误,所以bash认为所有命令都执行成功了。
如果我们把echo 和ls换一个顺序:
$ cat t.sh
#!/usr/bin/env bash
set -e
echo "0000"
echo "hehe" | ls *.notexist
echo "9999"
$ ./t.sh
0000
ls: cannot access *.notexist: No such file or directory
$ echo $?
2
此时就触发了命令返回值非零的条件。
命令set -o pipefail
就是用来解决这个问题,就是pipeline中的命令出错了,把这个非零返回值往后传递,作为整行命令的返回值。
$ cat t.sh
#!/usr/bin/env bash
set -e
set -o pipefail
echo "0000"
echo "hehe---000" | ls *.notexist | echo "hehe---999"
echo "9999"
$ ./t.sh
0000
hehe---999
ls: cannot access *.notexist: No such file or directory
$ echo $?
2
最后这个2就是pipe中的命令ls *.notexist
的返回值。
注意:如果一个pipeline里面有多个命令执行返回非零值,后面的会覆盖前面的,即最后一个命令的非零返回值被返回:
#!/usr/bin/env bash
set -e
set -o pipefail
function foo() {
echo "foo-000"
return 9
}
echo "0000"
echo "hehe---000" | foo | ls *.notexist | echo "hehe---999"
echo "9999"
此时的返回值是2,即ls *.notexist
的返回值。而:
#echo "hehe---000" | ls *.notexist | foo | echo "hehe---999"
的返回值是9,即foo()
的返回值。因为他们都是整个pipe的最后一个非零返回值。