2016-12-26 206 views
0

首先,我不知道我是否正確地制定問題。 所以我有一個bash腳本刪除系統中的用戶。問題是,它顯示終端代碼之前的錯誤信息。 這裏。 代碼:Bash腳本stderr和stdout

echo -e "\nCommencing user $UserName removal" 
echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)" 
echo -e "Listing group(s) user: " "$(groups $UserName)" 
echo -e "Removing Crontab ... " "$(crontab -r -u $UserName)" 

這裏是輸出:

Commencing user Test2 removal 
chsh: unknown user: Test2 
Deactivating Test2 shell account ... 
groups: Test2: no such user 
Listing group(s) user: 
scripts/sudo.sh: line 332: /delete_Test2/crontab.bak: No such file or directory 
Saving Crontab ... 

刪除的用戶是Test2的,這是這種情況下「所謂的」不存在時(爲不同的時間不同的問題)。現在,不應該將stderr味精顯示在命令旁邊還是下面,而不是上面呢?

預先感謝

回答

3

當shell執行行echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName)",這裏是事件的順序:

  1. 外殼運行chsh -s /usr/bin/false Test2,其標準輸出去捕捉緩衝區,所以外殼以後可以使用它。
  2. chsh發現「Test2」不存在,並將「chsh:unknown user:Test2」打印到它的stderr。由於shell沒有對stderr做任何特殊的處理,所以這直接到了shell的stderr,它是你的終端。
  3. chsh退出
  4. 殼取所捕捉的輸出:從chsh(注意標準輸出,而不是標準錯誤)(有沒有任何),和替代入echo命令行,得到echo -e "Deactivating Test2 shell account ..." ""

注該錯誤信息被打印在第2步,但有關將要發生什麼的消息直到第4步纔會打印出來。

有幾種方法可以解決此問題;通常最好的做法是避免捕獲命令輸出的整個混亂,然後迴應它。這毫無意義,只會導致這樣的混亂(以及其他一些你沒有遇到過的)。只需直接運行該命令,並讓其輸出(stdout和stderr)按正常順序進入正常位置。

順便說一句,我也建議避免echo -e,或確實echo -anythingPOSIX standard for echo說「實現不應該支持任何選項。」實際上,有些實現可以支持選項;其他人只是將它們視爲要打印的字符串的一部分。另外,一些解釋轉義序列(如\n)要打印的字符串中,有些則不需要,有些只在指定-e(違反POSIX標準)的情況下執行。鑑於這些功能是多麼不可預測,最好避免這種不確定的情況,並且使用printf來代替(使用起來更復雜,但更可預測),或者(如您的情況),只需使用單獨的echo命令線。

此外,你應該總是用雙引號變量引用(以下EG groups "$UserName"代替groups $UserName),以防它們包含空格,通配符等

基於上述,這裏就是我會寫的腳本:

echo # print a blank line 
echo "Commencing user $UserName removal" 
echo "Deactivating $UserName shell account ..." 
chsh -s /usr/bin/false "$UserName" 

echo "Listing group(s) user: " 
groups "$UserName" 

echo "Removing Crontab ... " 
crontab -r -u "$UserName" 
+0

感謝大家。戈登,你和伊格納西奧回答工作;然而,我從你身上學到的是,我不需要回應我的命令!並確保將用戶名放在引號中以防萬一。謝謝 – user3112318

1

現在,應該不是stderr的MSG顯示旁邊的命令或低於它,而不是上面呢?

不,因爲命令先執行,然後然後它的輸出被回顯。在兩個單獨的行中執行回顯和命令。

1

這是因爲chsh寫入stderr 之前 bash有機會寫入stdout。將stderr重定向到標準輸出正確:

echo -e "Deactivating $UserName shell account ..." "$(chsh -s /usr/bin/false $UserName 2>&1)" 

通常,最好在嘗試停用用戶之前檢查用戶是否存在。