天天看點

linux中的set指令:

工作中經常在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

2

3

4

5

6

7

<code>#!/bin/bash</code>

<code>set</code> <code>-e</code>

<code>...</code>

<code>/home/work/</code><code>...</code><code>/hadoop</code> <code>dfs -rmr </code><code>/app/</code><code>...</code><code>/dir</code>

<code>/home/work/</code><code>...</code><code>/hadoop</code> <code>dfs -</code><code>mkdir</code> <code>/app/</code><code>...</code><code>/dir</code>

<code>/home/work/</code><code>...</code><code>/hadoop</code> <code>dfs -put file_1 </code><code>/app/</code><code>...</code><code>/dir/</code>

這幾行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."

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

<code># test.sh</code>

<code>set</code> <code>-o pipefail</code>

<code>ls</code> <code>.</code><code>/a</code><code>.txt |</code><code>echo</code> <code>"hi"</code> <code>&gt;</code><code>/dev/null</code>

<code>echo</code> <code>$?</code>

運作test.sh,因為目前目錄并不存在a.txt檔案,輸出:

ls: ./a.txt: No such file or directory

1 #設定了set -o pipefail,傳回從右往左第一個非零傳回值,即ls的傳回值1

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

0 # 沒有set -o pipefail,預設傳回最後一個管道指令的傳回值

本文轉自 Mr_sheng 51CTO部落格,原文連結:http://blog.51cto.com/sf1314/2062784

繼續閱讀