一文帶你簡單理解linux中的輸入輸出重定向
linux簡單理解輸入輸出重定向
linux重定向可以分為輸出重定向和輸入重定向。在系統(tǒng)中除了標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、錯誤輸出以外,其他的重定向,都需要指定文件描述符id,也可以稱為句柄。
在linux中,可以通過查看/proc/進程pid號/fd/下的文件來查看該進程有多少個fd,比如:
# ls -l /proc/$$/fd/ total 0 lrwx------. 1 root root 64 Jun 3 22:22 0 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 1 -> /dev/pts/0 lrwx------. 1 root root 64 Jun 3 22:22 2 -> /dev/pts/0 #
上述命令中$$表示該進程本身的pid,而該fd文件下,可以看到有0、1、2 三個文件,都指向/dev/pts/0,這是一個字符設(shè)備文件,表示當(dāng)前的終端。
輸出重定向原理
對于系統(tǒng)而言,任何一個程序都有2個輸出,分別是:
- 文件描述符為1的標(biāo)準(zhǔn)輸出
- 文件描述符為2的錯誤輸出
所以,當(dāng)執(zhí)行一個命令輸出重定向的時候,比如:
command >> filename
上述命令是將command命令執(zhí)行的標(biāo)準(zhǔn)輸出結(jié)果重定向到filename文件中,你可以理解為在執(zhí)行該命令的時候,其進程標(biāo)準(zhǔn)輸出文件描述符1由默認(rèn)的/dev/pts/0指向了filename文件,為此可以來寫一個程序來試試。
程序如下:
#!/bin/bash
echo "pid: $$" >&2
while true
do
echo 123
sleep 3
done
這個程序非常簡單,首先現(xiàn)輸出該腳本的pid到錯誤輸出上,即文件描述符為2,而后定一個無限循環(huán),每隔3秒輸出123。
在執(zhí)行的時候,將該文件輸出重定向到filename中。
# bash test.sh >> filename pid: 42699
程序執(zhí)行會卡主,這是正常的,這是因為有無限循環(huán),每隔3秒會輸出123字符串至標(biāo)準(zhǔn)輸出上。
而后打開一個新的終端,查看42699的fd文件信息。
# ls -l /proc/42699/fd/ total 0 lrwx------. 1 root root 64 Jun 3 23:41 0 -> /dev/pts/0 l-wx------. 1 root root 64 Jun 3 23:41 1 -> /root/fd/filename lrwx------. 1 root root 64 Jun 3 23:41 2 -> /dev/pts/0 lr-x------. 1 root root 64 Jun 3 23:41 255 -> /root/fd/test.sh #
通過上面執(zhí)行的結(jié)果可以發(fā)現(xiàn),其標(biāo)準(zhǔn)輸出,文件描述符為1已經(jīng)指向一個文件:/root/fd/filename,而非終端字符設(shè)備。所以說,在上面案例中,重定向后,實際上是將句柄給改寫到文件中,所以屏幕沒有輸出任何數(shù)據(jù)。基于此,標(biāo)準(zhǔn)輸入和錯誤輸出的原理也是這樣的。
輸出重定向
輸出重定向一般格式為:[n]>[|]filename,其中n是文件描述符,>|表示覆蓋保護繞過機制,不過一般不用,即常用的寫法為:[n]>filename。
比如,將字符串abcdef的標(biāo)準(zhǔn)輸出重定向到filename中:
echo "abcdef" 1> filename
默認(rèn)情況下,1>可以縮略寫為>,這也是常用的寫法:
echo "abcde" > filename
將命令dasdsada的錯誤結(jié)果寫入到文件filename中:
dasdsada 2> filename
因為沒有這個命令,所以一定會報錯-bash: dasdsada: command not found。
對于該重定向而言,它在執(zhí)行前會清理掉原始內(nèi)容,從而寫入新的內(nèi)容。
除此之外,還有追加重定向,其格式為[n]>>filename,其中n是文件描述符,>>表示追加,它不會清理掉原有內(nèi)容。比如將abc追加到文件filename中。
echo 123 1>> filename
同樣的,也可以將1>>縮略寫為>>。
將命令aaa的錯誤結(jié)果追加寫入到文件filename中:
aaa 2>> filename
輸入重定向
在linux系統(tǒng)中,任何一個程序的標(biāo)準(zhǔn)輸入文件描述符id為0,而輸入重定向一般格式為[n]<filename,其中n表示文件描述符。
所以,如下命令:
cat 0< filename
它的意思是將filename文件的內(nèi)容作為標(biāo)準(zhǔn)輸入提供給cat調(diào)用,結(jié)果是打印了filename的內(nèi)容,上述命令中的0<可以縮略寫為<。
不僅如此,還能在循環(huán)中,搭配read,將文件的信息按行讀取。
比如有以下文件內(nèi)容:
# cat filename aa bb cc dd #
有腳本內(nèi)容如下:
#!/bin/bash
while read ll
do
echo read_at: ${ll}
done 0< filename
上述腳本表示將filename文件作為輸入源,供while調(diào)用,按照的方式是read命令按行調(diào)用,將行內(nèi)容賦值到ll變量上,這個變量名稱可以自定義。
其結(jié)果為:
# bash test.sh read_at: aa read_at: bb read_at: cc read_at: dd #
輸入重定向還有一種表達方式是here-documents。表示多行定義輸入,其語法為:
command [n]<<word here doc word
其中n表示文件操作符,如果省略,則使用默認(rèn)的文件操作符0,而后是關(guān)鍵字<<,word是自定義的結(jié)束符,讓后續(xù)讀取到word后停止讀取。
比如:
cat <<END 123 456 789 END
輸出的結(jié)果為
123
456
789
上述命令中的END是可以替換為任何字符串的,只要后續(xù)出現(xiàn)該字符串就會停止輸入,注意這個字符,一定是要在單獨的一行出現(xiàn)的,不能有其他字符,包括空格。
here-documents會進行命令替換,變量替換等,比如有如下命令:
# x=123
# cat <<END
${x}
$(pwd)
aa
bb
cc
END
輸出的結(jié)果會先進行命令替換,變量替換等,比如將${x}替換為123,將$(pwd)替換為當(dāng)前目錄。如果不想其被替換,則需要添加單引號進行轉(zhuǎn)義。
重定向的順序
注意看,如下有2條命令:
ls -l > filename 2>&1
和
ls -l 2>&1 > filename
所執(zhí)行的結(jié)果是完全不一樣的,第一條命令是將標(biāo)準(zhǔn)輸出和錯誤輸出都寫入到filename中,而第二條則是將錯誤輸出輸出到屏幕上,而將標(biāo)準(zhǔn)輸出寫入到文件中,如果不是很明白,可以嘗試拆解一下命令:
首先,命令的前提是:標(biāo)準(zhǔn)輸出 和 錯誤輸出 都在某個設(shè)備上,比如pty終端,假設(shè)設(shè)備為/dev/pts/0,所以文件描述符信息為:
1 -> /dev/pts/02 -> /dev/pts/0
然后第一條命令,ls -l > filename 其實是將文件描述符1給指向了文件filename,這個時候,文件描述符信息為:
1 -> filename2 -> /dev/pts/0
這個時候再使用2>&1表示將錯誤消息也寫入到文件描述符為1的文件中,即filename,所以最后的文件描述符為:
1 -> filename2 -> filename
而第二條命令,一開始都是輸出到某個設(shè)備上:
1 -> /dev/pts/02 -> /dev/pts/0
這個時候,它將錯誤輸出指向2>&1,而文件描述符為1是/dev/pts/0,所以這第一步,就沒動過,而第二部則是將標(biāo)準(zhǔn)輸出指向filename,即:
1 -> filename2 -> /dev/pts/0
所以第二條命令,錯誤輸出輸出到屏幕上,而將標(biāo)準(zhǔn)輸出寫入到文件中。
總結(jié)
要理解輸入輸出重定向,一定要理解文件的描述符!對于每個進程,都會產(chǎn)生3個默認(rèn)的文件描述符,分別是 標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出 和 錯誤輸出,用文件描述符id:0、1、2 來表示。
其重定向就是修改這些文件描述符的指向,將他們指向到文件中即可。
對于輸入重定向而言,有一種表達方式是here-documents,它可以和輸出重定向結(jié)合,將終端中輸入的文件寫入到文件中,比如:
cat 1>> filename 0<<END a b c d e END
表示將終端輸入的a、b... e字符提供給cat命令,而cat將內(nèi)容重定向到文件filename中。可以發(fā)現(xiàn)上面有1>>表示將標(biāo)準(zhǔn)輸出的內(nèi)容重定向到某個文件,0<<表示將標(biāo)準(zhǔn)輸入的內(nèi)容重定向到某個文件,上述命令中的1>>可以縮寫為>>,而0<<可以縮寫為<<。
到此這篇關(guān)于一文帶你簡單理解linux中的輸入輸出重定向的文章就介紹到這了,更多相關(guān)linux輸入輸出重定向內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Shell中使用plink工具實現(xiàn)遠程批量關(guān)機
這篇文章主要介紹了Shell中使用plink工具實現(xiàn)遠程批量關(guān)機,Plink 是命令行工具,執(zhí)行遠程服務(wù)器上的命令,需要的朋友可以參考下2014-12-12
Linux Shell腳本系列教程(六):數(shù)組和關(guān)聯(lián)數(shù)組
這篇文章主要介紹了Linux Shell腳本系列教程(六):數(shù)組和關(guān)聯(lián)數(shù)組,本文講解了什么是數(shù)組和關(guān)聯(lián)數(shù)組、定義打印普通數(shù)組、定義打印關(guān)聯(lián)數(shù)組等內(nèi)容,需要的朋友可以參考下2015-06-06
ubuntu修改terminal終端的主機名的實現(xiàn)方法
這篇文章主要介紹了ubuntu修改terminal終端的主機名的實現(xiàn)方法的相關(guān)資料,希望通過本文能幫助大家,需要的朋友可以參考下2017-08-08
Linux shell實現(xiàn)每天定時備份mysql數(shù)據(jù)庫
這篇文章主要介紹了Linux shell實現(xiàn)每天定時備份mysql數(shù)據(jù)庫的代碼,分享給大家,希望大家能夠喜歡。2015-03-03
Linux shell實現(xiàn)HTTP服務(wù)示例代碼
這篇文章介紹的是如何實現(xiàn)一個可以調(diào)用shell腳本的HTTP服務(wù),本文給出了詳細(xì)的示例代碼,有需要的可以參考借鑒。2016-08-08

