shell 中的 set命令 -e -o 選項作用


工作中經常在shell腳本中看到set的這兩個用法,但就像生活中的很多事情,習慣導致忽視,直到出現問題才引起關注。

1. set -e
set命令的-e參數,linux自帶的說明如下:
"Exit immediately if a simple command exits with a non-zero status."
也就是說,在"set -e"之后出現的代碼,一旦出現了返回值非零,整個腳本就會立即退出。有的人喜歡使用這個參數,是出於保證代碼安全性的考慮。但有的時候,這種美好的初衷,也會導致嚴重的問題。

真實案例:
腳本a.sh開頭使用了"set -e",且能正常運行。在幾個月或更久以后,因需求升級,在腳本中增加了3行hadoop操作:

1 #!/bin/bash
2 set -e
3 ...
4 /home/work/.../hadoop dfs -rmr /app/.../dir
5 /home/work/.../hadoop dfs -mkdir /app/.../dir
6 /home/work/.../hadoop dfs -put file_1 /app/.../dir/
7 ...

 

這幾行hadoop命令邏輯很簡單:在hdfs上清除並新建一個目錄,並將一份本地文件推送至這個目錄,供后續使用。將這幾行單拎出來,在命令行下執行,除了提示待刪除的目錄不存在,並沒有什么問題,文件還是會被推送到指定的地方。

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

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

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

2. set -o pipefail
對於set命令-o參數的pipefail選項,linux是這樣解釋的:
"If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a  non-zero  status,or zero if all commands in the pipeline exit successfully.  This option is disabled by default."

設置了這個選項以后,包含管道命令的語句的返回值,會變成最后一個返回非零的管道命令的返回值。聽起來比較繞,其實也很簡單:

1 # test.sh
2 set -o pipefail
3 ls ./a.txt |echo "hi" >/dev/null
4 echo $?

 

運行test.sh,因為當前目錄並不存在a.txt文件,輸出:

ls: ./a.txt: No such file or directory
1  # 設置了set -o pipefail,返回從右往左第一個非零返回值,即ls的返回值1

注釋掉set -o pipefail 這一行,再次運行,輸出:

ls: ./a.txt: No such file or directory
0  # 沒有set -o pipefail,默認返回最后一個管道命令的返回值

————————————————

版權聲明:本文為CSDN博主「期待一片自己的藍天」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/nyist327/article/details/52017261


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM