Linux Basics-重定向與管道:第一部分
概述
本教程將介紹 Linux 中重定向標準 IO 流的基本技術。學習:
-
什么是重定向與標準 IO 流:標準輸入、標準輸出和標準錯誤
-
各種流和管道的實際應用
前提條件
你應該了解 Linux 基本知識以及擁有一個正常工作的 Linux 系統,在本文說明的實例中,我采用是CentOS 7 內核版本是3.10,它適用于大多數linux(如果不知道自己的內核版本,可以通過在命令行中輸入命令uname -a來查詢 )
重定向和流
在linux發展到今天,許多工作是通過腳本來完成,這樣做的好處就是可以提高效率,而且運維人員可以做到自動化的運維,省去了每天重復一樣的操作,而且也避免了因為個人失誤而帶來的許多問題,想要做到自動化運維就少不了要編寫bash腳本,linux中重要的哲學就是避免要和用戶交互,而且重定向和流的使用就是完全符合了這樣的要求。
概念介紹
文件描述符(File descriptor)
在操作系統中每個程序的打開都要經過系統管理,而系統管理進程或者程序的運行就是通過文件描述符來管理,文件描述符在形式上是一個非負整數。實際上,它是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表。當程序打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫往往會圍繞著文件描述符展開。每個Unix進程(除了可能的守護進程)應均有三個標準的POSIX文件描述符,對應于三個標準流:
整數值 |
名稱 |
<stdio.h>文件流 |
0 |
stdin |
|
1 |
stdout |
|
2 |
stderr |
stdout是 標準輸出流,它顯示來自命令的輸出。它擁有文件描述符 1。
stderr是 標準錯誤流,它顯示來自命令的錯誤輸出。它擁有文件描述符 2。
stdin是 標準輸入流,它向命令提供輸入。它擁有文件描述符 0。
重定向標準 IO
盡管標準輸入和輸出模型是發往和來自 ASCII 終端的順序字符流,但是我們想要把文本文件中的字符發給終端,或者是想要上一條命令的結果發給某個文件或者程序,總之需求多多,這個時候就要用到重定向
重定向是以出現的順序進行處理的,從左到右。
注意重定向的順序非常重要。例如,命令
ls > dirlist 2>&1
將標準輸出和標準錯誤重定向到文件 dirlist, 而命令
ls 2>&1 > dirlist
只會將標準輸出重定向到文件 dirlist, 因為在標準輸出被重定向到文件 dirlist 中之前,標 準錯誤被復制為標準輸出。
一些文件名在重定向中被 bash 特殊處理,如下表所示:
/dev/fd/fd
如果 fd 是一個合法的整數,文件描述符 fd 將被復制 。
/dev/stdin
文件描述符 0 被復制。
/dev/stdout
文件描述符1 被復制 。
/dev/stderr
文件描述符2 被復制 。
/dev/tcp/host/port
如果host 是一個合法的主機名或internet地址 ,并且 port 是一個整數端口號或服務名,bash 試圖建立與相應的socket (套 接 字 )的TCP連接。
/dev/udp/host/port
如果 host 是一個合法的主機名或Internet地址,并且 port 是一個整數端口號或服務名,bash試圖建立與相應的socket (套 接 字 )的UDP連接。
打開或創建文件錯誤將導致重定向出錯
1.重定向輸出(Redirecting Output)
它的格式是
[n]>word
可通過兩種方式將輸出重定向到文件:
<1>Redirecting Output 重定向輸出
格式:
n>word
將來自文件描述符 n的輸出重定向到某個文件。您必須擁有該文件的寫權限。如果該文件不存在,則需要創建它。如果它已經存在,通常會毫無預兆地丟失現有內容。
<2>Appending Redirected Output (添加到重定向后的輸出尾部)
格式:
n>> word
這種方式的輸出重定向使得以 word 擴展結名的文件被打開并通過文件描述符 n 從尾部添加。如果文件不存在,它將被創建。如果它已經存在,輸出會被附加到現有文件。n> 或 n>> 中的 n指的是 文件描述符。如果省略它,則會假設使用的是標準輸出(文件描述符 1)
可以使用內建命令 set的 noclobber選項來控制此行為。如果已設置它,可以使用 n>| 覆蓋它。如果啟用了內建命令 set 的 noclobber 選 項 , 那么如果 word 擴展后得到的文件名 存在并且是一個普通的文件,重定向將失敗。 如果重定向操作符是 >|, 或者重定向操作符 是 > 并且沒有啟用內建命令 set 的 noclobber 選 項 , 那么即使 word 得出的文件名存 在 也會嘗試進行重定向。
set -o noclobber命令或者set +C 來控制,set -C來取消,具體操作可以查看man幫助
下面是說明的演示:
LIST 1 . 創建準備文件
mkdir -p cdx1&& cd cdx1 && { echo -e "1 magedu\n2 linux\n3 M21" > text1 echo -e "4\tlear\n3\tkernel\n10\knowledge" > text2 echo "www.magedu.com. " >text3 ls; }
LIST 2 . 輸出重定向
從上述例子可以看出 文件描述符不同n>或者n>>重定向的內容也是不同的,而且n>和n>>作用也是不同,n>>可以重定向到尾部。
拓展知識(自行探索)
有時,您可能希望將標準輸出和標準錯誤都重定向到一個文件中。通常,會對自動化流程或后臺作業這么做,以便可以在以后檢查輸出。使用 &> 或 &>> 將標準輸出和標準錯誤都重定向到同一個位置。另一種方法是重定向文件描述符 n,然后使用結構 m>&n 或 m>>&n 將文件描述符 m重定向到相同位置。重定向輸出的順序很重要。例如,
command 2>&1 >output.txt
不同于
command >output.txt 2>&1
在第一種情況下,stderr 被重定向到當前的 stdout 位置,然后將 stdout 重定向到 output.txt,但第二次重定向僅會影響 stdout,而不會影響 stderr。在第二種情況下,stderr 被重定向到當前的 stdout 位置,也就是 output.txt
Redirecting Standard Output and Standard Error
Bash 允許使用這種結構將標準輸出和標準錯誤 (文件描述符 1 和 2) 重定向到以 word 擴 展結果為名的文件中。
有兩種重定向標準輸出/標準錯誤的形式:
&>word
還 有
>&word
兩種形式中 ,推薦使用第一種。它與
>word 2>&1
在語義上等價 。
Opening File Descriptors for Reading and Writing
重定向操作符
[n]<>word
使得以 word 擴展結果為名的文件被打開 ,通過文件描述符n 進行讀寫。如果沒有指定 n 那么就使用文件描述符0。如果文件不存在,它將被創建。
如下所示
Moving File Descriptors
重 定 向 操 作 符
[n]<&digit?
將文件描述符 digit 移動為文件描述符 n, 或標準輸入 (文件描述符 0),如果沒有指定 n 的 話 。 digit 復制為 n 之后就被關閉了。
類似的 重定向操作符
[n]>&digit?
將文件描述符 digit 移動為文件描述符 n, 或標準輸出(文件描述符1),如果沒有指定 n 的 話 。
<3>Here Documents
它將 << 和一個單詞結合構成一個標記,比如與 END 結合來表示輸入結束。LIST 3和4演示了此概念,LIST 3和4使用命令替換創建了一個強制制表符,然后創建了一段僅包含兩個 cat命令的很短的 shell 腳本,每個命令從一個 here-document 讀取信息。使用 END 作為從終端讀取的 here-document 的標記。如果在腳本中使用同一個單詞作為標記,則會導致過早結束輸入。所以,可使用 EOF 代替。創建腳本后,使用 .(點號)命令 導入它(.(點號)和source命令一樣,用于不重啟shell來讀取腳本或者配置文件生效)。
這種重定向使得shell從當前源文件讀取輸入 ,直到遇到僅包含 word 的一行(并且沒有尾部空白,trailing blanks)為止。直到這一點的所有行被用作命令的標準輸入 。
here-document 的格式是:
<<[?]word
here-document
delimiter
如果重定向操作符是 <<?, 那么所有前導的tab 字符都被從輸入行和包含 delimiter 的行 中刪除。這樣使得 shell 腳本中的here-document 可以被更好地縮進。
注意:
-
結尾的delimiter 一定要頂格寫,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 縮進。
-
開始的delimiter前后的空格會被忽略掉。
-
格式中word就是delimiter的意思
<4>Here Strings
here-document 的變種 ,形式是
<<<word
word 被擴展 ,提供給命令作為標準輸入。
LIST 3 . 使用 here-document 的輸入重定向
LIST 4 . 使用 here-document 的輸入重定向
<5>/dev/null 文件
如果希望執行某個命令,但又不希望在屏幕上顯示輸出結果,那么可以將輸出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一個特殊的文件,寫入到它的內容都會被丟棄;如果嘗試從該文件讀取內容,那么什么也讀不到。但是 /dev/null 文件非常有用,將命令的輸出重定向到它,會起到”禁止輸出“的效果。
如果希望屏蔽 stdout 和 stderr,可以這樣寫:
$ command > /dev/null 2>&1
2. 重定向輸入(Redirecting Input )
重定向輸入使得以 word 擴展結果為名的文件被打開并通過文件描述符 n 讀取 ,如果沒有指定 n 那么就作為標準輸入(文件描述符為0)讀取 。
重定向輸入的一般形式是:
[n]<word
具體用法參見重定向輸出
命令 |
說明 |
command > file |
將輸出重定向到 file。 |
command < file |
將輸入重定向到 file。 |
command >> file |
將輸出以追加的方式重定向到 file。 |
n > file |
將文件描述符為 n 的文件重定向到 file。 |
n >> file |
將文件描述符為 n 的文件以追加的方式重定向到 file。 |
n >& m |
將輸出文件 m 和 n 合并。 |
n <& m |
將輸入文件 m 和 n 合并。 |
<< tag |
將開始標記 tag 和結束標記 tag 之間的內容作為輸入。 |
重定向用法整理(來自網絡)
簡單重定向
-
cmd > file
把cmd命令的輸出重定向到文件file中。如果file已經存在,則清空原有文件,使用bash的noclobber選項可以防止覆蓋原有文件。
-
cmd >> file
把cmd命令的輸出重定向到文件file中,如果file已經存在,則把信息加在原有文件后面。
-
cmd < file
使cmd命令從file讀入
-
cmd << text
從命令行讀取輸入,直到一個與text相同的行結束。除非使用引號把輸入括起來,此模式將對輸入內容進行shell變量替換。如果使用 <<- ,則會忽略接下來輸入行首的tab,結束行也可以是一堆tab再加上一個與text相同的內容,可以參考后面的例子。
-
cmd <<< word
把word(而不是文件word)和后面的換行作為輸入提供給cmd。
-
cmd <> file
以讀寫模式把文件file重定向到輸入,文件file不會被破壞。僅當應用程序利用了這一特性時,它才是有意義的。
-
cmd >| file
功能同>,但即便在設置了noclobber時也會覆蓋file文件,注意用的是|而非一些書中說的!,目前僅在csh中仍沿用>!實現這一功能。
使用文件描述符的重定向
使用文件描述符的重定向都使用了&符號。
cmd >&n |
把輸出送到文件描述符n |
cmd m>&n |
把輸出 到文件符m的信息重定向到文件描述符n |
cmd >&- |
關閉標準輸出 |
cmd <&n |
輸入來自文件描述符n |
cmd m<&n |
m來自文件描述符n |
cmd <&- |
關閉標準輸入 |
cmd <&n- |
移動輸入文件描述符n而非復制它。(需要解釋) |
cmd >&n- |
移動輸出文件描述符 n而非復制它。(需要解釋) |
注意:
>&實際上復制了文件描述符,這使得ls > dirlist 2>&1與ls 2>&1 > dirlist的效果不一樣。man bash的Redirection節中提及了這段內容。
重定向的組合應用
cmd 2>file |
把文件描述符2重定向到file,即把錯誤輸出存到file中。 |
cmd > file 2>&1 |
把標準錯誤重定向到標準輸出,再重定向到file,即stderr和stdout都被輸出到file中 |
cmd &> file |
功能與上一個相同,更為簡便的寫法。 |
cmd >& file |
功能仍與上一個相同。 |
cmd > f1 2>f2 |
把stdout重定向到f1,而把stderr重定向到f2 |
參考資料
IBM中國linux專區
Wiki
Redirection Definition http://www.linfo.org/redirection.html
網絡博客
原創文章,作者:M21-郝建勛,如若轉載,請注明出處:http://www.www58058.com/54471