1. 程式人生 > >Unix/Linux 指令碼中 “set -e” 的作用

Unix/Linux 指令碼中 “set -e” 的作用

1 2 #!/bin/bash set  -e

  在檔案開頭加上set -e,這句語句告訴bash如果任何語句的執行結果不是true則應該退出。

  這樣的好處是防止錯誤像滾雪球般變大導致一個致命的錯誤,而這些錯誤本應該在之前就被處理掉。如果要增加可讀性,可以使用set -o errexit,它的作用與set -e相同。

  使用-e幫助你檢查錯誤。如果你忘記檢查(執行語句的結果),bash會幫你執行。

 

也就是說,在"set -e"之後出現的程式碼,一旦出現了返回值非零,整個指令碼就會立即退出。有的人喜歡使用這個引數,是出於保證程式碼安全性的考慮。但有的時候,這種美好的初衷,也會導致嚴重的問題。

網上案例:
指令碼a.sh開頭使用了"set -e",且能正常執行。在幾個月或更久以後,因需求升級,在指令碼中增加了3行hadoop操作:
#!/bin/bash
set -e
...
/home/work/.../hadoop dfs -rmr /app/.../dir
/home/work/.../hadoop dfs -mkdir /app/.../dir
/home/work/.../hadoop dfs -put file_1 /app/.../dir/
...
這幾行hadoop命令邏輯很簡單:在hdfs上清除並新建一個目錄,並將一份本地檔案推送至這個目錄,供後續使用。將這幾行單拎出來,在命令列下執行,除了提示待刪除的目錄不存在,並沒有什麼問題,檔案還是會被推送到指定的地方。

但第一次執行這個指令碼的時候,卻失敗退出了,且導致呼叫該指令碼的程式整體退出,造成了嚴重的後果。原因是hdfs上還沒有這個目錄,rmr這一行會返回255,這個值被指令碼前方的"set -e"捕捉到,直接導致了指令碼退出。

新增的程式碼本身並沒有問題,先刪除再新建目錄,反而是保證資料安全的比較規範的操作,刪除命令本身的容錯性,可以保證後續命令正常執行。事實是這個指令碼有好幾百行,且邏輯比較複雜,在增加這幾行程式碼的時候,開發人員已經不記得這個腳本里還有個"set -e"埋伏著了。

可見設定"set -e",在指令碼開發過程中可能很有幫助,而在開發完成後,特別是對於後期可能有升級的指令碼,則可能是埋下了安全隱患。

   
1 2 #!/bin/bash set  -e

  在檔案開頭加上set -e,這句語句告訴bash如果任何語句的執行結果不是true則應該退出。

  這樣的好處是防止錯誤像滾雪球般變大導致一個致命的錯誤,而這些錯誤本應該在之前就被處理掉。如果要增加可讀性,可以使用set -o errexit,它的作用與set -e相同。

  使用-e幫助你檢查錯誤。如果你忘記檢查(執行語句的結果),bash會幫你執行。

 

也就是說,在"set -e"之後出現的程式碼,一旦出現了返回值非零,整個指令碼就會立即退出。有的人喜歡使用這個引數,是出於保證程式碼安全性的考慮。但有的時候,這種美好的初衷,也會導致嚴重的問題。

網上案例:
指令碼a.sh開頭使用了"set -e",且能正常執行。在幾個月或更久以後,因需求升級,在指令碼中增加了3行hadoop操作:
#!/bin/bash
set -e
...
/home/work/.../hadoop dfs -rmr /app/.../dir
/home/work/.../hadoop dfs -mkdir /app/.../dir
/home/work/.../hadoop dfs -put file_1 /app/.../dir/
...
這幾行hadoop命令邏輯很簡單:在hdfs上清除並新建一個目錄,並將一份本地檔案推送至這個目錄,供後續使用。將這幾行單拎出來,在命令列下執行,除了提示待刪除的目錄不存在,並沒有什麼問題,檔案還是會被推送到指定的地方。

但第一次執行這個指令碼的時候,卻失敗退出了,且導致呼叫該指令碼的程式整體退出,造成了嚴重的後果。原因是hdfs上還沒有這個目錄,rmr這一行會返回255,這個值被指令碼前方的"set -e"捕捉到,直接導致了指令碼退出。

新增的程式碼本身並沒有問題,先刪除再新建目錄,反而是保證資料安全的比較規範的操作,刪除命令本身的容錯性,可以保證後續命令正常執行。事實是這個指令碼有好幾百行,且邏輯比較複雜,在增加這幾行程式碼的時候,開發人員已經不記得這個腳本里還有個"set -e"埋伏著了。

可見設定"set -e",在指令碼開發過程中可能很有幫助,而在開發完成後,特別是對於後期可能有升級的指令碼,則可能是埋下了安全隱患。