有些开发人员会用Bash来实现很复杂的功能,就像使用别的高级语言同样。他可能以为本身很牛逼但其余人早就想锤爆他了,Bash的可读性和可维护性远远低于任何高级语言。更要命的是,Bash并无方便的调试工具和防错机制,出了问题你要排查半天。安全
在Ruby或者Python等高级语言里,你很容易知道错误是哪行什么类型的错误,还有IDE的Debugger加持。而Bash只能看源码,经过打印log等很是低效的方式调试。bash
本文将介绍Bash中 set -euxo pipefail
,它们能够帮助你写出更容易维护也更安全的脚本。这也是Bash脚本的终极调试手段,但愿你之后在本身的脚本中加上这么一行,头顶也能少秃一点。工具
set -e
选项可让你的脚本在出现异常时立刻退出,后续命令再也不执行。默认状况下Shell脚本不会由于错误而结束执行,但大多数状况是,咱们但愿出现异常时就不要再往下走了。假如你的if
判断条件里会出现异常,这时脚本也会直接退出,但可能这并非你指望的状况,这时你能够在判断语句后加上 || true
来阻止退出。测试
#!/bin/bash # 'foo' is a non-existing command foo echo "bar" # output # ------ # line 4: foo: command not found # bar
#!/bin/bash set -e # 'foo' is a non-existing command foo echo "bar" # output # ------ # line 5: foo: command not found
阻止当即退出的例子。调试
#!/bin/bash set -e # 'foo' is a non-existing command foo || true echo "bar" # output # ------ # line 5: foo: command not found # bar
默认状况下Bash只会检查管道(pipeline)操做最后一个命令的返回值,假如最右边的命令成功那么它就认为这个语句没问题。这个行为实际上是很不安全的,因此就有了set -o pipefail
。这个特别的选项表示在管道链接的命令中,只要有任何一个命令失败(返回值非0),则整个管道操做被视为失败。只有管道中全部命令都成功执行了这个管道才算成功执行。code
#!/bin/bash set -e # 'foo' is a non-existing command foo | echo "a" echo "bar" # output # ------ # a # line 5: foo: command not found # bar
#!/bin/bash set -eo pipefail # 'foo' is a non-existing command foo | echo "a" echo "bar" # output # ------ # a # line 5: foo: command not found
set -u
比较容易理解,Bash会把全部未定义的变量视为错误。默认状况下Bash会将未定义的变量视为空,不会报错,这也是不少坑的来源。也许因为变量名的细微差异让你查半天最后骂骂咧咧。ip
#!/bin/bash set -eo pipefail echo $a echo "bar" # output # ------ # # bar
#!/bin/bash set -euo pipefail echo $a echo "bar" # output # ------ # line 5: a: unbound variable
set -x
可让Bash把每一个命令在执行前先打印出来,你能够认为这就是Bash的Debug开关。它的好处固然显而易见,方便你快速找到有问题的脚本位置,可是也坏处也有吧,就是Bash的log会格外的乱。另外,它在打印命令前会把变量先解析出来,因此你能够知道当前执行的语句的变量值是什么。纵然log可能会乱一些,总比头发乱一些好,因此建议仍是打开这个开关。开发
#!/bin/bash set -euxo pipefail a=5 echo $a echo "bar" # output # ------ # + a=5 # + echo 5 # 5 # + echo bar # bar
以上就是关于 set -euxo pipefail
的介绍,从Shell脚本的编写角度看,我十分建议全部人都应该在本身的Shell脚本里加上这么一行。但从实际状况看,若是你的Shell脚本已经超过200行,我更建议你换成高级语言来实现。好比Python或者Ruby甚至Perl,这些高级语言在Linux系统都是内置的,注意版本兼容性就好,写起来比Shell舒服太多了。get
关于做者:源码
Toby Qin, Python 技术爱好者,目前从事测试开发相关工做,转载请注明原文出处。
欢迎关注个人博客 https://betacat.online,你能够到个人公众号中去当吃瓜群众。