寫SHELL好久了,經常被異常困擾,可竟然堅持了若干年沒用過,回想以前服務過的公司,阿彌陀佛,罪過罪過。廢話少說,希望此篇文章可以協助大家和我徹底結束SHELL腳本就是LINUX命令集合的初級階段。
一、STDOUT、STDERR
如果要獲取SHELL腳本的異常輸出,就需要首先理解SHELL命令的標准輸出STDOUT、標准錯誤STDERR。
當我們在編寫 shell 腳本時,我們會非常頻繁地操作執行命令的標准輸入stdin、標准輸出stdout、標准錯誤stderr。當我們執行腳本文件或者執行一個 shell 命令的時候,單從終端輸出我們很難區分哪些是標准輸出,哪些是標准錯誤。所以我們把這些信息重定向特定的地方,以便於我們分析腳本文件及 shell 命令的執行情況,這就用到了文件描述符。文件描述符是與打開文件或者數據流相關聯的整數,0、1、2 是系統保留的三個文件描述符,分別對應標准輸入、標准輸出、標准錯誤。Linux Shell 使用 " > " ">>" 進行對文件描述符進行重定位。例如代碼:
#!/bin/bash ls liqiu > /tmp/error #很明顯這是一個錯誤的命令 echo $? #捕獲上一條命令的輸出 (if 0 正常 else 錯誤) ls -l > /tmp/log echo $?
輸出結果:
@~ $ ~/study/test.sh ls: liqiu: No such file or directory 1 0
1 說明`ls liqiu > /tmp/error`執行錯誤,0 說明ls -l > /tmp/log執行成功。那么希望的記過是/tmp/error報錯錯誤日志,/tmp/log保存正確的結果,可查看文件發現不是這么回事。
@~ $ more /tmp/log total 0 drwx------ 3 liqiu staff 102 4 26 2014 Applications drwx------+ 4 liqiu staff 136 11 2 17:06 Desktop drwxr-xr-x 4 liqiu staff 136 10 18 09:56 svn @~ $ more /tmp/error @~ $
原因在於:重定位運算符 ">" 的默認參數為標准輸出 stdout ,即 1 ; 所以 ">" 等價於 "1>"; 上面的代碼等價於:
#!/bin/bash ls liqiu 1> /tmp/error echo $? #捕獲上一條命令的輸出 (if 0 正常 else 錯誤) ls -l 1> /tmp/log echo $?
二、捕獲異常
所以要捕獲異常,需要修改代碼:
#!/bin/bash ls liqiu > /tmp/error 2>&1 #使用 " 2>&1" 把標准錯誤 stderr 重定向到標准輸出 stdout ; echo $? #捕獲上一條命令的輸出 (if 0 正常 else 錯誤) ls -l > /tmp/log echo $?
執行之后,發現錯誤信息出現在了文件/tmp/log中。
@~ $ cat /tmp/error ls: liqiu: No such file or directory @~ $