簡述:
shell腳本中經常會出現在一個命令cmd后面跟着 >/dev/null 2>&1,本文詳細理清一下shell重定向。
為什么需要重定向?
shell腳本在執行的過程中,會有一些系統打印,有的是標准輸出,有的是錯誤輸出,這里的錯誤輸出不一定是指shell腳本有問題,而是系統打印的一些異常或者錯誤輸出,不影響系統運行的。一般shell腳本都是相較復雜多指令的。這里有個問題,C語言程序中調用shell腳本,一般是用 system 來調用,這里就有一個問題,system執行過程中,shell腳本是否順利執行完畢,要看執行期間有沒有被異常信號中斷,如果出現異常信號,system調用的shell則會終止。
這里我們需要做的就是去掉system調用的shell腳本中的異常輸出,這里就需要shell重定向輸出了。
shell重定向
當執行shell命令時,會默認打開3個文件,每個文件有對應的文件描述符來方便我們使用:
類型 | 文件描述符 | 默認情況 | 對應文件句柄位置 |
---|---|---|---|
標准輸入(standard input) | 0 | 從鍵盤獲得輸入 | /proc/self/fd/0 |
標准輸出(standard output) | 1 | 輸出到屏幕(即控制台) | /proc/self/fd/1 |
錯誤輸出(error output) | 2 | 輸出到屏幕(即控制台) | /proc/self/fd/2 |
我們可以看下具體信息
root@LEDE:/proc/392/fd# ls -all dr-x------ 2 root root 0 Jul 23 10:36 . dr-xr-xr-x 8 root root 0 Jul 23 09:48 .. lr-x------ 1 root root 64 Jul 23 10:36 0 -> /dev/ttyS0 l-wx------ 1 root root 64 Jul 23 10:36 1 -> /dev/ttyS0 lrwx------ 1 root root 64 Jul 23 10:36 10 -> /dev/tty l-wx------ 1 root root 64 Jul 23 10:36 2 -> /dev/ttyS0
/dev/ttyS0對應的就是串行端口終端。
輸出重定向
輸出重定向的使用方式很簡單,基本的一些命令如下:
命令 | 介紹 |
---|---|
command >filename | 把標准輸出重定向到新文件中 |
command 1>filename | 同上 |
command >>filename | 把標准輸出追加到文件中 |
command 1>>filename | 同上 |
command 2>filename | 把標准錯誤重定向到新文件中 |
command 2>>filename | 把標准錯誤追加到新文件中 |
我們使用>或者>>對輸出進行重定向。符號的左邊表示文件描述符, 如果沒有的話表示1,也就是標准輸出 ,符號的右邊可以是一個文件,也可以是一個輸出設備。當使用>時,會判斷右邊的文件存不存在,如果存在的話就先刪除,然后創建一個新的文件,不存在的話則直接創建。但是當使用>>進行追加時,則不會刪除原來已經存在的文件。
舉例:
root@LEDE:/tmp# touch exist.txt root@LEDE:/tmp# ls exist.txt notexist.txt 1>out ls: notexist.txt: No such file or directory root@LEDE:/tmp# cat out exist.txt root@LEDE:/tmp# ls exist.txt notexist.txt 1>>out ls: notexist.txt: No such file or directory root@LEDE:/tmp# cat out exist.txt exist.txt root@LEDE:/tmp# ls exist.txt notexist.txt 2>err exist.txt root@LEDE:/tmp# cat err ls: notexist.txt: No such file or directory root@LEDE:/tmp# ls exist.txt notexist.txt >out 2>err root@LEDE:/tmp# cat out exist.txt root@LEDE:/tmp# cat err ls: notexist.txt: No such file or directory
輸入重定向
對輸入進行重定向的基本命令:
命令 | 介紹 |
---|---|
command <filename | 以filename文件作為標准輸入 |
command 0<filename | 同上 |
command <<delimiter | 從標准輸入中讀入,直到遇到delimiter分隔符 |
我們使用<對輸入做重定向時, 如果符號左邊沒有寫值,那么默認就是0。
請用cat進行試驗。
/dev/null
手抄一段《linux shell腳本攻略》描述:
/dev/null是一個特殊的設備文件,這個文件接收到的任何數據都會被丟棄。因此,null這個設備通常也被稱為位桶(bit bucket)或黑洞。
簡單地理解就是,重定向操作給這個/dev/null文件的所有東西都會被丟棄。
因為這些文件描述符輸出的字符串,總是會顯示出來的。如果我們在shell編程的時候,操作到某一條命令的返回結果,我們不想要這個時候又不想讓這個輸出結果打印到屏幕上,我們就可以重定向到/dev/null這個文件來,由/dev/null這個文件負責處理后事。
這個丟棄的結果又不能粗暴的認為是刪除錯誤輸出,這個操作是一個丟棄重定向輸入輸出的操作。
>filename 2>&1
1.2>&1,將錯誤輸出綁定到標准輸出上。由於此時的標准輸出是默認值,也就是輸出到屏幕,所以錯誤輸出會輸出到屏幕。
2.>filename, 將標准輸出1重定向到filename中。
>/dev/null 2>&1 VS >/dev/null 2>/dev/null
首先command > file 2>file 的意思是將命令所產生的stdout標准輸出信息和stderr錯誤的輸出信息送到file 中。command > file 2>file 這樣的寫法,stdout和stderr都直接送到file中,file會被打開兩次,這樣stdout和stderr會互相覆蓋,這樣寫相當使用了FD1和FD2兩個同時去搶占file的管道。
而command >file 2>&1 這條命令就將stdout直接送向file,stderr 繼承了FD1管道后,再被送往file,這種寫法file文件只被打開了一次,即只使用了一個管道FD1就包括了stdout和stderr的內容。
從IO效率上,command >file 2>&1命令的效率要比command > file 2>file的命令效率高,所以在編寫shell腳本時,我們較多時間使用command > file 2>&1的寫法。
END