對於任何一個進程,在啓動時,都會打開三個流:stdin(標準輸入), stdout(標準輸出), stderr(標準錯誤輸出)。Stdout,stderr是process與Display之間,stdin是process與keyboard之間。也就是說系統的標準輸入輸出,是進程與設備間交流的橋樑。linux
可是在不少狀況下,咱們的程序數據並不來自於標準輸入,咱們在使用標準輸出時,也不但願寫到顯示器上,多是文件,網絡,打印機等。這時候就須要IO Redirect來做用了。還有,爲了方便使用等,咱們但願將寫到Stdout的數據做爲另一個進程的輸入,其實這也是IO redirect的一種,不過它有個特殊的名字——pipe。網絡
操做系統內核會爲每個進程分配不少file handler(也叫 File Description),其中初始時會分配3個handle,用數字0,1,2來表示,分別分配給了stdin, stdout, stderr。其餘的則是隨着須要分配的。app
這樣一來,就能夠直接使用0,1,2來表示Stdio了。操作系統
在linux上使用lsof -p pid查看一個進程打開了哪些文件。下面是一個查看運行中的top命令的狀況:code
< 將標準輸入(stdin, 0)重定向,也就是說數據來源不是鍵盤,而是其餘,例如文件等。blog
> 將標準輸出(stdout, 1)重定向,也就是說數據再也不寫到顯示器,而是其餘地方。進程
其中在 >,< 操做符的左邊,只能是FD,右邊多是file,也能夠是FD等。此外, <等價於 <1, >等價於1>,因此2> 就是將標準錯誤輸出(stderr, 2)重定向。ip
IO redirect的本質是什麼呢?在我看來本質是FD的賦值。怎麼理解呢?pip
默認狀況下一個,一個進程(例如:ls)是這樣的:io
對於一個進程而言: #0 = keyboard #1 = display #2 = display
ls >a:表明了 fd1=a #0 = keyboard #1 = a #2 = display
Ls 3>a :表明了fd3=a
sort<file.txt :表明了fd0=file.txt
若是但願在多個FD之間進行賦值運算,那麼就用>&或者<&。
那麼理解上仍是 >時賦值運算符,&則是dup2系統調用了。
2>&1的意思就是 對 FD1執行dup2,獲得FD1的拷貝,而後賦值給FD2,也就是說FD1指向了誰,FD2也去指向誰。
例如:
3>file.txt 2>&3 表明了:FD3-->file.txt,那麼FD2--->file.txt
須要注意的是:>自己不要求文件必須是存在的,可是通過了上述複製並賦值操做和後,啓動進程之初就要準備好相應的流,此時就須要文件file.txt必須是存在的。
若是將stdout或者stderr 重定向到一個文件,但文件裏已經有內容,會是什麼結果呢?使用 > file時,文件中已有的內容會被truncate掉,也就是文件內容被清除了。
若是想要保留文件內容怎麼辦呢?
有一個變體操做符:>> 以append的方式重定向。
若是但願將輸出內容,直接做爲另一個程序的輸入,這種技術成爲Pipe,可以進行Pipe的進程,必須是父子進程。用「|」 來表示管道。Pipe也是進程間通訊的一種技術。
例如:lsof -p pid | grep xxx ,父進程是 lsof, 子進程是grep。
本篇內容適用於 Windows,Linux,Unix等操做系統。