有些開發人員會用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,你能夠到個人公衆號中去當吃瓜羣衆。