linux shell數據重定向(輸入重定向與輸出重定向)詳細分析

導讀小文:【http://www.ibm.com/developerworks/cn/linux/l-iotips/ html

技巧:Linux I/O重定向的一些小技巧 linux

簡介: Linux I/O 重定向雖然很簡單,但在腳本編寫、系統管理時卻要經常打交道,搞清其中使用技巧很是有用。 shell

首先說一下什麼是I/O重定向,所謂I/O重定向簡單來講就是一個過程,這個過程捕捉一個文件,或者命令,程序,腳本,甚至腳本中的代碼塊(code block)的輸出,而後把捕捉到的輸出,做爲輸入發送給另一個文件,命令,程序,或者腳本。 centos

標準輸入一般指鍵盤的輸入 
標準輸出一般指顯示器的輸出 

標準錯誤一般也是定向到顯示器 app

#ls /dev 1>filename                                  #注意:"1"和">"中間沒有空格 學習

以上命令會把命令的標準輸出從新定向到一個文件filename,而不是顯示到屏幕上,若是不指明文件標識符, 系統默認的就是1, 所以1能夠省略
若是把上面例子重的">"改爲">>"則表示把輸出追加到filename文件的末尾,若是文件不存在則建立它。以下
# ls /dev >>filename

# ls -qw  /dev  2>filename     :把標準錯誤從新定向到文件

#ls /dev &>filename     :"&"在這裏表明標準輸出和標準錯誤,這裏不管是正常輸出仍是錯誤信息都寫到filename中了。 spa

從新定義文件標識符能夠用i>&j命令,表示把文件標識符i從新定向到j,能夠把"&"理解爲"取地址"

請看如下例子 code

#exec 5>&1    :表示把文件標識符5定向到標準輸出,這個命令一般用來臨時保存標準輸入 htm

"&-"表示關閉文件標識符 blog

有關關閉文件標識符的操做請參考下面
n<&- 關閉輸入文件標識符n
0<&-或<&- 關閉標準輸入stdin
n>&- 關閉輸出文件標識符n
1>&-或>&-關閉標準輸出stdout

:> filename 或者 > filename
表示把文件filename設置成空,也就是清空文件內容,若是文件不存在,則建立一個空文件(等同於touch命令)。:表示一個空輸出,兩個命令的惟一區別就是>filename不是在全部shell均可以正常工做的。


  • 常常須要將輸出顯示在屏幕同時還要輸出到一個文件中,能夠例如:
  • make 2>&1 | tee m.txt
  • tee將標準輸入複製到每一個指定文件,並顯示到標準輸出。
    -a, --append 內容追加到給定的文件而非覆蓋
    -i, --ignore-interrupts 忽略中斷信號




linux shell數據重定向(輸入重定向與輸出重定向)詳細分析


在瞭解重定向以前,咱們先來看看linux 的文件描述符。

linux文件描述符:能夠理解爲linux跟蹤打開文件,而分配的一個數字,這個數字有點相似c語言操做文件時候的句柄,經過句柄就能夠實現文件的讀寫操做。 用戶能夠自定義文件描述符範圍是:3-num,這個最大數字,跟用戶的:ulimit –n 定義數字有關係,不能超過最大值。 

linux啓動後,會默認打開3個文件描述符,分別是:標準輸入standard input 0,正確輸出standard output 1,錯誤輸出:error output 2

之後打開文件後。新增文件綁定描述符 能夠依次增長。 一條shell命令執行,都會繼承父進程的文件描述符。所以,全部運行的shell命令,都會有默認3個文件描述符。 

對於任何一條linux 命令執行,它會是這樣一個過程:

image

一個命令執行了:

先有一個輸入:輸入能夠從鍵盤,也能夠從文件獲得

命令執行完成:成功了,會把成功結果輸出到屏幕:standard output默認是屏幕

命令執行有錯誤:會把錯誤也輸出到屏幕上面:standard error默認也是指的屏幕 

文件輸入輸出由追蹤爲一個給定的進程全部打開文件的整數句柄來完成。這些數字值就是文件描述符。最爲人們所知的文件米描述符是 stdinstdout 和 stderr,文件描述符的數字分別是0,1和2。這些數字和各自的設備是保留的。一個命令執行前,先會準備好全部輸入輸出,默認分別綁定(stdin,stdout,stderr),若是這個時候出現錯誤,命令將終止,不會執行。命令解析過程,能夠參考:Linux Shell 通配符、元字符、轉義符使用實例介紹

這些默認的輸出,輸入都是linux系統內定的,咱們在使用過程當中,有時候並不但願執行結果輸出到屏幕。我想輸出到文件或其它設備。這個時候咱們就須要進行輸出重定向了。

linux shell下經常使用輸入輸出操做符是:

1.  標準輸入   (stdin) :代碼爲 0 ,使用 < 或 << ; /dev/stdin -> /proc/self/fd/0   0表明:/dev/stdin 
2.  標準輸出   (stdout):代碼爲 1 ,使用 > 或 >> ; /dev/stdout -> /proc/self/fd/1  1表明:/dev/stdout
3.  標準錯誤輸出(stderr):代碼爲 2 ,使用 2> 或 2>> ; /dev/stderr -> /proc/self/fd/2 2表明:/dev/stderr

 

  • 輸出重定向:

格式:

command-line1 [1-n] > file或文件操做符或設備

上面命令意思是:將一條命令執行結果(標準輸出,或者錯誤輸出,原本都要打印到屏幕上面的)  重定向其它輸出設備(文件,打開文件操做符,或打印機等等)1,2分別是標準輸出,錯誤輸出。

實例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#顯示當前目錄文件 test.sh test1.sh test1.sh實際不存在
[chengmo@centos5 shell]$ls test.sh test1.sh
ls: test1.sh: 沒有這個文件和目錄
test.sh
 
#正確輸出與錯誤輸出都顯示在屏幕了,如今須要把正確輸出寫入suc.txt
# 1>能夠省略,不寫,默認所至標準輸出
[chengmo@centos5 shell]$ls test.sh test1.sh 1>suc.txt
ls: test1.sh: 沒有這個文件和目錄
[chengmo@centos5 shell]$cat suc.txt
test.sh
 
#把錯誤輸出,不輸出到屏幕,輸出到err.txt
[chengmo@centos5 shell]$ls test.sh test1.sh 1>suc.txt 2>err.txt
[chengmo@centos5 shell]$cat suc.txt err.txt
test.sh
ls: test1.sh: 沒有這個文件和目錄
#繼續追加把輸出寫入suc.txt err.txt  「>>」追加操做符
[chengmo@centos5 shell]$ls test.sh test1.sh 1>>suc.txt 2>>err.txt
 
#將錯誤輸出信息關閉掉
[chengmo@centos5 shell]$ls test.sh test1.sh 2>&-
test.sh
[chengmo@centos5 shell]$ls test.sh test1.sh 2>/dev/null
test.sh
#&[n] 表明是已經存在的文件描述符,&1 表明輸出 &2表明錯誤輸出 &-表明關閉與它綁定的描述符
#/dev/null 這個設備,是linux 中黑洞設備,什麼信息只要輸出給這個設備,都會給吃掉
 
#關閉全部輸出
[chengmo@centos5 shell]$ls test.sh test1.sh  1>&- 2>&-
#關閉 1 ,2 文件描述符
[chengmo@centos5 shell]$ls test.sh test1.sh  2>/dev/null 1>/dev/null
#將1,2 輸出轉發給/dev/null設備
[chengmo@centos5 shell]$ ls test.sh test1.sh >/dev/null 2>&1
#將錯誤輸出2 綁定給 正確輸出 1,而後將 正確輸出 發送給 /dev/null設備  這種經常使用
<p>[chengmo@centos5 shell]$ls test.sh test1.sh &>/dev/null
#& 表明標準輸出 ,錯誤輸出 將全部標準輸出與錯誤輸出 輸入到/dev/null文件
</p>

  

注意:

一、shell遇到」>」操做符,會判斷右邊文件是否存在,若是存在就先刪除,而且建立新文件。不存在直接建立。 不管左邊命令執行是否成功。右邊文件都會變爲空。

二、「>>」操做符,判斷右邊文件,若是不存在,先建立。以添加方式打開文件,會分配一個文件描述符[不特別指定,默認爲1,2]而後,與左邊的標準輸出(1)或錯誤輸出(2) 綁定。

三、當命令:執行完,綁定文件的描述符也自動失效。0,1,2又會空閒。

四、一條命令啓動,命令的輸入,正確輸出,錯誤輸出,默認分別綁定0,1,2文件描述符。

五、一條命令在執行前,先會檢查輸出是否正確,若是輸出設備錯誤,將不會進行命令執行

  • 輸入重定向

格式:

command-line [n] <file或文件描述符&設備

將然有,命令默認從鍵盤得到的輸入,改爲從文件,或者其它打開文件以及設備輸入。執行這個命令,將標準輸入0,與文件或設備綁定。將由它進行輸入。

實例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[chengmo@centos5 shell]# cat > catfile
testing
cat file test
#這裏按下 [ctrl]+d 離開
#從標準輸入【鍵盤】得到數據,而後輸出給catfile文件
 
[chengmo@centos5 shell]$cat>catfile <test.sh
#cat 從test.sh 得到輸入數據,而後輸出給文件catfile
 
 
[chengmo@centos5 shell]$cat>catfile <<eof
test afile
test!
eof
 

#<< 這個連續兩個小符號, 他表明的是『結束的輸入字符』的意思。

#這樣當空行輸入eof字符,輸入自動結束,不用ctrl+D

 

 

  • exec綁定重定向

格式:

exec 文件描述符[n] <或> file或文件描述符或設備

在上面講的輸入,輸出重定向 將輸入,輸出綁定文件或設備後。只對當前那條指令是有效的。若是須要在綁定以後,接下來的全部命令都支持的話。就須要用exec命令

實例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[chengmo@centos5 shell]$exec 6>&1
#將標準輸出與fd 6綁定
 
[chengmo@centos5 shell]$ls  /proc/self/fd/ 
0  1  2  3  6
#出現文件描述符6
 
[chengmo@centos5 shell]$exec 1>suc.txt
#將接下來全部命令標準輸出,綁定到suc.txt文件(輸出到該文件)
 
[chengmo@centos5 shell]$ls -al
#執行命令,發現什麼都不返回了,由於標準輸出已經輸出到suc.txt文件了
 
[chengmo@centos5 shell]$exec 1>&6
#恢復標準輸出
 
 
[chengmo@centos5 shell]$exec 6>&-
#關閉fd 6描述符
 
[chengmo@centos5 ~]$ls /proc/self/fd/
0  1  2  3

說明:使用前先將標準輸入保存到文件描述符6,這裏說明下,文件描述符默認會打開0,1,2 還可使用自定義描述符 。而後對標準輸出綁定到文件,接下來全部輸出都會發生到文件。 使用完後,恢復標準的輸出,關閉打開文件描述符6。

【個人理解:&1表示輸出符1的地址,因此「exec 6>&1」便是將6描述符重定向到1描述符的地址(標準輸出地址),因而6的地址也就是系統中標準輸出的地址;而後將1描述符重定向到文件:「exec 1>suc.txt」;以後又將1定向到6的地址:「exec 1>&6」;最後禁用6描述符,也就是刪除6描述符的指向,這個指向以前被定義指到標準輸出地址,這個地址是不變的,若是以前不利用6來接替1的指向,後面想1指回標準輸出地址就很難辦到了

有趣事情:

可能有朋友會這樣用:exec 1>suc.txt ,接下來全部輸出都綁定到suc.txt 文件,那麼怎麼樣恢復原來的呢? 試試你就會發現問題所在……

  • 複雜一點實例
?
1
2
3
4
5
6
7
8
9
10
11
exec 3<>test.sh;
#打開test.sh可讀寫操做,與文件描述符3綁定
 
while read line<&3
 do
    echo $line;
done
#循環讀取文件描述符3(讀取的是test.sh內容)
exec 3>&-
exec 3<&-
#關閉文件的,輸入,輸出綁定

 

  • 總結下:

學習就要總結,總結才能夠提升了。哈哈!

估計還有一些朋友是頭暈暈的。怎麼linux的重定向這麼複雜呢,又是文件打開描述符又是讀,還有些,還有默認標準輸入輸出。

其實,總結一下,重定向應用一般就如下兩點:

一、從新設置命令的默認輸入,輸出,指向到本身文件(文件,文件描述符,設備其實都是文件,由於linux就是基於設備也是文件,描述符也指向是文件,哈哈)

二、擴展本身新的描述符,對文件進行讀寫操做

相關文章
相關標籤/搜索