有些開發人員會用Bash來實作很復雜的功能,就像使用別的高級語言一樣,他可能覺得自己很牛逼但其他人早就想錘爆他了,Bash的可讀性和可維護性遠遠低于任何高級語言,更要命的是,Bash并沒有方便的除錯工具和防錯機制,出了問題你要排查半天,
在Ruby或者Python等高級語言里,你很容易知道錯誤是哪行什么型別的錯誤,還有IDE的Debugger加持,而Bash只能看原始碼,通過列印log等非常低效的方式除錯,
本文將介紹Bash中 set -euxo pipefail,它們可以幫助你寫出更容易維護也更安全的腳本,這也是Bash腳本的終極除錯手段,希望你以后在自己的腳本中加上這么一行,頭頂也能少禿一點,
set -e
set -e 選項可以讓你的腳本在出現例外時馬上退出,后續命令不再執行,默認情況下Shell腳本不會因為錯誤而結束執行,但大多數情況是,我們希望出現例外時就不要再往下走了,假如你的if判斷條件里會出現例外,這時腳本也會直接退出,但可能這并不是你期望的情況,這時你可以在判斷陳述句后加上 || true 來阻止退出,
Before
#!/bin/bash
# 'foo' is a non-existing command
foo
echo "bar"
# output
# ------
# line 4: foo: command not found
# bar
After
#!/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
set -o pipefail
默認情況下Bash只會檢查管道(pipeline)操作最后一個命令的回傳值,假如最右邊的命令成功那么它就認為這個陳述句沒問題,這個行為其實是很不安全的,所以就有了set -o pipefail,這個特別的選項表示在管道連接的命令中,只要有任何一個命令失敗(回傳值非0),則整個管道操作被視為失敗,只有管道中所有命令都成功執行了這個管道才算成功執行,
Before
#!/bin/bash
set -e
# 'foo' is a non-existing command
foo | echo "a"
echo "bar"
# output
# ------
# a
# line 5: foo: command not found
# bar
After
#!/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
set -u 比較容易理解,Bash會把所有未定義的變數視為錯誤,默認情況下Bash會將未定義的變數視為空,不會報錯,這也是很多坑的來源,也許由于變數名的細微差別讓你查半天最后罵罵咧咧,
Before
#!/bin/bash
set -eo pipefail
echo $a
echo "bar"
# output
# ------
#
# bar
After
#!/bin/bash
set -euo pipefail
echo $a
echo "bar"
# output
# ------
# line 5: a: unbound variable
set -x
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舒服太多了,
關于作者:
Toby Qin, Python 技術愛好者,目前從事測驗開發相關作業,轉載請注明原文出處,
歡迎關注我的博客 https://betacat.online,你可以到我的公眾號中去當吃瓜群眾,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/207112.html
標籤:Python
下一篇:Python 進行目標檢測

