bash的set -e和set -o pipefail

2021-10-20  本文已影响0人  CodingCode
  1. 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()内其他的命令也都没有执行了。

$ 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就停止执行并返回那个非零值。

  1. 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的最后一个非零返回值。

上一篇下一篇

猜你喜欢

热点阅读