Bash 脚本中的 set -euxo pipefail
在Ruby或者Python等高级语言里,你很容易知道错误是哪行什么类型的错误,还有IDE的Debugger加持。而Bash只能看源码,通过打印log等非常低效的方式调试。
本文将介绍Bash中 set -euxo pipefail
,它们可以帮助你写出更容易维护也更安全的脚本
set -e
set -e
选项可以让你的脚本在出现异常时马上退出,后续命令不再执行。默认情况下Shell脚本不会因为错误而结束执行,但大多数情况是,我们希望出现异常时就不要再往下走了。假如你的if
判断条件里会出现异常,这时脚本也会直接退出.
如果不想立即退出,可以使用 || true
来阻止退出。
set -o pipefail
默认情况下Bash只会检查管道(pipeline)操作最后一个命令的返回值,假如最右边的命令成功那么它就认为这个语句没问题。这个行为其实是很不安全的,所以就有了set -o pipefail
。这个特别的选项表示在管道连接的命令中,只要有任何一个命令失败(返回值非0),则整个管道操作被视为失败。只有管道中所有命令都成功执行了这个管道才算成功执行。
set -u
set -u
比较容易理解,Bash会把所有未定义的变量视为错误。默认情况下Bash会将未定义的变量视为空,不会报错
除了 $*
和 $@
,对您之前未定义的任何变量的引用都是一个错误,并导致程序立即退出。
set -x
set -x
可以让Bash把每个命令在执行前先打印出来,你可以认为这就是Bash的Debug开关。它的好处当然显而易见,方便你快速找到有问题的脚本位置,但是也坏处也有吧,就是Bash的log会格外的乱。另外,它在打印命令前会把变量先解析出来,所以你可以知道当前执行的语句的变量值是什么。纵然log可能会乱一些,总比头发乱一些好,所以建议还是打开这个开关。
Setting IFS
IFS 变量,代表内部字段分隔符
#!/bin/bash
IFS=$' '
items="a b c"
for x in $items; do
echo "$x"
done
IFS=$'\n'
for y in $items; do
echo "$y"
done
... will print out this:
a
b
c
a b c
对于第一个循环,IFS 是一个空格,这意味着单词由空格字符分隔。
对于第二个循环,“单词”由换行符分隔,这意味着 bash 将“项目”的整个值视为一个单词。如果 IFS 有多个字符,则将对这些字符中的任何一个进行拆分。
为什么我们要将 IFS 设置为由制表符和换行符组成的字符串?因为它在迭代循环时为我们提供了更好的行为。不太可能导致令人惊讶和令人困惑的错误。