linux重定向
從定義上來看,Linux重定向就是指修改原來默認的一些東西,對原來系統命令的默認執行方式進行改變,比如說簡單的我不想看到在顯示器的輸出而是希望輸出到某一文件中就可以通過Linux重定向來進行這項工作。在進一步探索重定向之前,我們先理解一下linux文件描述符。
linux文件描述符
文件描述符理解為linux跟蹤打開文件,而分配的一個數字,這個數字有點類似c語言操作文件時候的句柄,通過句柄就可以實現文件的讀寫操作。 用戶可以自定義文件描述符范圍是:3-num,這個最大數字,跟用戶的:ulimit –n 定義數字有關系,不能超過最大值。
linux啟動后,會默認打開3個文件描述符,分別是:標准輸入standard input 0,正確輸出standard output 1,錯誤輸出:error output 2,每個文件有對應的文件描述符來方便我們使用:
類型 | 文件描述符 | 默認情況 | 對應文件句柄位置 |
---|---|---|---|
標准輸入(standard input) | 0 | 從鍵盤獲得輸入 | /proc/self/fd/0 |
標准輸出(standard output) | 1 | 輸出到屏幕(即控制台) | /proc/self/fd/1 |
錯誤輸出(error output) | 2 | 輸出到屏幕(即控制台) | /proc/self/fd/2 |
通常,一個命令執行過程如下:
先有一個輸入:輸入可以從鍵盤,也可以從文件得到;
命令執行完成:成功了,會把成功結果輸出到屏幕:standard output默認是屏幕;
命令執行有錯誤:會把錯誤也輸出到屏幕上面:standard error默認也是指的屏幕;
所以我們平時在執行shell命令中,都默認是從鍵盤獲得輸入,並且將結果輸出到控制台上。但是我們可以通過更改文件描述符默認的指向,從而實現輸入輸出的重定向。比如我們將1指向文件,那么標准的輸出就會輸出到文件中。接下來我們進一步的介紹Linux中的輸入重定向和輸出重定向。
輸出重定向
輸出重定向的使用方式很簡單,基本的一些命令格式如下:
命令 | 介紹 |
---|---|
command >file | 把標准輸出(stdout)重定向到 file 文件中; |
command 1>file | 同上; |
command >>file | 把 stdout 重定向到 file 文件中(追加); |
command 1>>file | 同上; |
command 2>file | 把標准錯誤(stderr)重定向到 file 文件中; |
command 2>>file | 把 stderr重定向到 file 文件中(追加); |
command >> file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中(追加); |
cmd > file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中; |
cmd >> file 2>&1 | 把 stdout 和 stderr 一起重定向到 file 文件中(追加); |
我們使用>
或者>>
對輸出進行重定向。符號的左邊表示文件描述符,如果沒有的話表示1,也就是標准輸出,符號的右邊可以是一個文件,也可以是一個輸出設備。當使用>
時,會判斷右邊的文件存不存在,如果存在的話就先刪除,然后創建一個新的文件,不存在的話則直接創建。但是當使用>>
進行追加時,則不會刪除原來已經存在的文件。
格式:
command-line1 [1-n] > file或文件操作符或設備
這條命令意思是:將一條命令執行結果(標准輸出,或者錯誤輸出,本來都要打印到屏幕上面的) 重定向其它輸出設備(文件,打開文件操作符,或打印機等等)1,2分別是標准輸出,錯誤輸出。
實例:
#查看文件內容,1.txt 2.txt (其中2.txt文件不存在) [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt this is a.txt cat: 2.txt: No such file or directory #標准輸出與錯誤輸出都顯示在屏幕了, #現在需要把標准輸出寫入到1.log中 # 1>可以省略,表示標准輸出 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>1.log cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt >1.log cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]#cat 1.log this is a.txt #標准輸出不輸出到屏幕,輸出到1.log中 #錯誤輸出不輸出到屏幕,輸出到2.log中 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>1.log 2>2.log [root@sccprocddev02:/home/upro01]#cat 1.log 2.log this is a.txt cat: 2.txt: No such file or directory #將標准輸出和錯誤輸出分別追加到文件1.log和2.log中 “>>”追加操作符 #可以看到兩個文件分別多出一行輸出的內容 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>>1.log 2>>2.log [root@sccprocddev02:/home/upro01]#cat 1.log 2.log this is a.txt this is a.txt cat: 2.txt: No such file or directory cat: 2.txt: No such file or directory [root@sccprocddev02:/home/upro01]# 高級用法 #將錯誤輸出信息關閉掉,控制台只打印了標准輸出 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 2>&- this is a.txt [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 2>/dev/null this is a.txt #&[n] 代表是已經存在的文件描述符,&1 代表輸出 &2代表錯誤輸出&-代表關閉與它綁定的描述符 #/dev/null 這個設備,是linux 中黑洞設備,什么信息只要輸出給這個設備,都會給吃掉 #關閉所有輸出 #關閉 1 ,2 文件描述符 [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt 1>&- 2>&- #將1,2 輸出轉發給/dev/null設備 [chengmo@centos5 shell]$ ls test.sh test1.sh 2>/dev/null 1>/dev/null [root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt >/dev/null 2>&1 #將錯誤輸出2綁定給正確輸出1,然后將正確輸出發送給 /dev/null設備 這種常用
#文件描述符前必須有個 &, 否則2>1就變成將錯誤輸出輸出到一個名為1的文件了
[root@sccprocddev02:/home/upro01]#cat 1.txt 2.txt &>/dev/null #& 代表所有文件描述符,該命令會將所有標准輸出與錯誤輸出輸入到/dev/null文件
輸入重定向
在理解了輸出重定向之后,理解輸入重定向就會容易得多。對輸入重定向的基本命令如下:
命令 | 介紹 |
---|---|
command <filename | 以filename文件作為標准輸入 |
command 0<filename | 同上 |
command <<delimiter | 從標准輸入中讀入,直到遇到delimiter分隔符 |
command < file >file2 | command命令以 file 文件作為標准輸入(stdin),以 file2文件作為stdout; |
cat <>file | 以讀寫的方式打開 file; |
我們使用<
對輸入做重定向,如果符號左邊沒有寫值,那么默認就是0。
格式:
command-line [n] <file或文件描述符&設備
命令默認從鍵盤獲得的輸入,使用輸入重定向改成從文件,或者其它打開文件以及設備輸入。執行這個命令,將標准輸入0,與文件或設備綁定。將由它進行輸入。
實例:
[root@sccprocddev02:/home/upro01]#cat > stdout.txt this is stdout.txt ^C [root@sccprocddev02:/home/upro01]#cat stdout.txt this is stdout.txt #這里使用ctrl+d 或者ctrl+c退出輸入 #從標准輸入[鍵盤]獲得數據,然后輸出給stdout.txt文件 [root@sccprocddev02:/home/upro01]#cat > stdout2.txt < stdout.txt [root@sccprocddev02:/home/upro01]#cat stdout2.txt this is stdout.txt #從stdout.txt獲得輸入數據,然后輸出給文件catfile [root@sccprocddev02:/home/upro01]#cat > stdout3.txt << end > first line > second line > end [root@sccprocddev02:/home/upro01]#cat stdout3.txt first line second line #<< 這個連續兩個小符號, 他代表的是[結束的輸入字符]的意思。這樣當空行輸入end字符時,自動退出輸入,不需要使用ctrl+d或者ctrl+c退出
高級用法
重定向綁定
前面的例子中我們執行過如下一條命令
cat 1.txt 2.txt >/dev/null 2>&1
這條命令其實分為兩命令,一個是>/dev/null
,另一個是2>&1
。
>/dev/null
這條命令的作用是將標准輸出1重定向到/dev/null中。/dev/null代表linux的空設備文件,所有往這個文件里面寫入的內容都會丟失,俗稱“黑洞”。那么執行了>/dev/null
之后,標准輸出就會不再存在,沒有任何地方能夠找到輸出的內容。
2>&1
這條命令用到了重定向綁定,采用&可以將兩個輸出綁定在一起。這條命令的作用是錯誤輸出將和標准輸出同用一個文件描述符,說人話就是錯誤輸出將會和標准輸出輸出到同一個地方。
linux在執行shell命令之前,就會確定好所有的輸入輸出位置,並且從左到右依次執行重定向的命令,所以>/dev/null 2>&1
的作用就是讓標准輸出重定向到/dev/null中(丟棄標准輸出),然后錯誤輸出由於重用了標准輸出的描述符,所以錯誤輸出也被定向到了/dev/null中,錯誤輸出同樣也被丟棄了。執行了這條命令之后,該條shell命令將不會輸出任何信息到控制台,也不會有任何信息輸出到文件中。
注意:這里的>/dev/null 和 2>&1的順序是不能寫反的,2>&1 >/dev/null這樣的寫法結果將是:標准錯誤打印到屏幕,而標准輸出不打印到屏幕。
我們用一個表格來更好地說明這兩條命令的區別:
命令 | 標准輸出 | 錯誤輸出 |
---|---|---|
>/dev/null 2>&1 | 丟棄 | 丟棄 |
2>&1 >/dev/null | 丟棄 | 屏幕 |
應用
在工作中我們常常會使用到重定向功能,比如在啟動java項目時,因為我們已經配置好了日志文件,所以我們不想輸出默認的nohup.out日志,那么我們通常會使用如下命令
# nohup java -jar xxxx.jar >/dev/null 2>&1 &
補充
使用exec綁定重定向
格式:
exec 文件描述符[n] <或> file或文件描述符或設備
在上面講的輸入,輸出重定向 將輸入,輸出綁定文件或設備后。只對當前那條指令是有效的。如果需要在綁定之后,接下來的所有命令都支持的話。就需要用exec命令
[root@sccprocddev02:/home/upro01]$ exec 6>&1 #將標准輸出與fd 6綁定 [root@sccprocddev02:/home/upro01]$ ls /proc/self/fd/ 0 1 2 3 6 #出現文件描述符6 [root@sccprocddev02:/home/upro01]$ exec 1>6.txt #將接下來所有命令標准輸出,綁定到6.txt文件(輸出到該文件) [root@sccprocddev02:/home/upro01]$ ls -al #執行命令,發現什么都不返回了,因為標准輸出已經輸出到6.txt文件了 [root@sccprocddev02:/home/upro01]$ exec 1>&6 #恢復標准輸出 [root@sccprocddev02:/home/upro01]$ exec 6>&- #關閉fd 6描述符 [root@centos5 ~]$ ls /proc/self/fd/ 0 1 2 3
說明:使用前先將標准輸入保存到文件描述符6,這里說明下,文件描述符默認會打開0,1,2 還可以使用自定義描述符 。然后對標准輸出綁定到文件,接下來所有輸出都會發生到文件。 使用完后,恢復標准的輸出,關閉打開文件描述符6。
>&n 使用系統調用 dup2復制文件描述符 n 並把結果用作標准輸出; <&n 標准輸入復制自文件描述符 n; <&- 關閉標准輸入(鍵盤); >&- 關閉標准輸出; n<&- 表示將 n 號輸入關閉; n>&- 表示將 n 號輸出關閉; 上述所有形式都可以前導一個數字,此時建立的文件描述符由這個數字指定而不是缺省的 0 或 1。如: ... 2>file 運行一個命令並把錯誤輸出(文件描述符 2)定向到 file。 ... 2>&1 運行一個命令並把它的標准輸出和輸出合並。(嚴格的說是通過復制文件描述符 1 來建立文件描述符 2 ,但效果通常是合並了兩個流。) 我 們對 2>&1詳細說明一下 :2>&1 也就是 FD2=FD1 ,這里並不是說FD2 的值 等於FD1的值,因為 > 是改變送出的數據通道,也就是說把 FD2 的 “數據輸出通道” 改為 FD1 的 “數據輸出通道”。如果僅僅這樣,這個改變好像沒有什么作用,因為 FD2 的默認輸出和 FD1的默認輸出本來都是 monitor,一樣的! 但是,當 FD1 是其他文件,甚至是其他 FD 時,這個就具有特殊的用途了。請大家務必理解這一點。 exec 1>outfilename # 打開文件outfilename作為stdout。 exec 2>errfilename # 打開文件 errfilename作為 stderr。 exec 0<&- # 關閉 FD0。 exec 1>&- # 關閉 FD1。 exec 5>&- # 關閉 FD5。
參考:
linux shell數據重定向(輸入重定向與輸出重定向)詳細分析