管道操作符 : |
我們在Linux下經(jīng)常要用到管道操作符,也就是"|",即一個豎線。這個操作符的作用對于經(jīng)常使用Linux的人來說,看上去十分直觀:
不就是將前一個指令的結(jié)果交給后一個指令嗎?
舉個例子:
cat system.log | grep hello復(fù)制代碼
上面的指令可以讓我們過濾出system.log這個文件中包含hello字符串的行,然后打印到屏幕上。
什么叫指令的結(jié)果
問題就來了,一個指令的結(jié)果是什么,這個說法十分混淆。
是指這個指令輸出的日志?是指這個指令的返回碼?(有些人可能不知道這東西)還是指啥啥啥的?
實(shí)際上,指令的結(jié)果這個概念并沒有一個嚴(yán)格定義,所以當(dāng)我們說,一個指令的結(jié)果的時候,經(jīng)常跟業(yè)務(wù)場景有關(guān)系。比如說,一個圖像處理程序的結(jié)果,就應(yīng)該是一個圖像,這才是合乎常理的。
如何描述 cat 指令的行為
首先我們來看一下 cat system.log 這個指令的行為。
也就是將 system.log 中的內(nèi)容打印到屏幕上。
這個過程可以細(xì)說,因?yàn)閷?nèi)容打印到屏幕上實(shí)際上還是不夠準(zhǔn)確。
那么這里就不得不牽扯出Linux下文件的一些概念。
程序打開文件以及文件描述符
在 Linux 系統(tǒng)中,一個程序是可以打開一個文件的,這個很容易理解。
那么進(jìn)程(一般正在運(yùn)行的程序稱之為進(jìn)程)是如何管理文件的呢?
那就是用文件描述符這種東西,這是一個數(shù)字以及與之相關(guān)聯(lián)的一堆數(shù)據(jù)。
一個進(jìn)程打開一個文件,就會創(chuàng)建一個新的文件描述符,這個數(shù)字一般是自增的。比如說,當(dāng)前的文件描述符是100。那么再打開一個新的文件,這個新的文件的描述符就是101。當(dāng)然進(jìn)程如果關(guān)閉文件,這個描述符是可以重復(fù)利用的。這里不多扯。
如果用圖來表示這個概念,應(yīng)該是下面的樣子:
我們可以看出,不同的數(shù)字代表了不同的文件。
那么在哪里能列出一個進(jìn)程所打開的文件呢?
在Linux下,可以先找到這個進(jìn)程的PID,假設(shè)是 20000
進(jìn)入如下的目錄:
cd /proc/20000/fd復(fù)制代碼
這個目錄存放的就是 20000 這個進(jìn)程所打開的文件了。ls一下,如圖:
正如我所描述的那樣,都是數(shù)字。
一些約定俗成的描述符
從上面的圖中,我們看到,描述符是從0開始的。那么0是什么文件呢?
在Linux下,每一個進(jìn)程啟動的時候,都會默認(rèn)打開三個文件,用0 ,1, 2來當(dāng)做他們的描述符。
那么0, 1, 2分別代表哪三個文件呢?
0 : 代表標(biāo)準(zhǔn)輸入1 : 代表標(biāo)準(zhǔn)輸出2 : 代表錯誤輸出
也許上面的描述,還是不夠清晰。
再進(jìn)一步,一般來說,
標(biāo)準(zhǔn)輸入,就是指 鍵盤輸入標(biāo)準(zhǔn)輸出,就是指輸出到屏幕錯誤輸出,也是指輸出到屏幕
文件描述符的作用
如果你在Linux下,寫過讀取鍵盤輸入的程序,那么就這樣理解。
你讀取的其實(shí)就是 0 這個描述符所代表的文件的內(nèi)容:也就是鍵盤。
如果你使用過類似 print 這種函數(shù),打印過日志的話,那么其實(shí)就是往 1 這個描述符所代表的文件里輸出內(nèi)容,對,這個內(nèi)容通過屏幕展現(xiàn)出來了。
實(shí)際上,這種讀取和寫入的操作,對于所有文件來說都是一樣的,至少在使用上來說,是一樣的。
都是先打開一個文件,給他一個描述符,然后針對這個描述符進(jìn)行讀或者寫。
文件和鍵盤輸入的關(guān)系
鍵盤輸入這種操作,在Linux里,會變成一個文件操作,就類似普通的文件那樣。這就是Linux的設(shè)計,一切皆是文件。不僅僅鍵盤操作和屏幕打印是文件操作。網(wǎng)絡(luò)連接讀取數(shù)據(jù)啥的,也都是文件操作,這些也都會產(chǎn)生文件描述符。一個進(jìn)程同時擁有的文件描述符是有上限的,這個上限可以設(shè)置。如果你不信,你可以試試同時打開一萬個文件,看看會不會報錯,如果報錯,觀察一下是報的什么錯。
可能是這樣的錯誤:
too many opened files復(fù)制代碼
回到管道操作符 |
cat system.log | grep hello復(fù)制代碼
我們現(xiàn)在再來描述上面整個指令:
1. cat system.log
cat這個程序打開了system.log這個文件,將system.log的內(nèi)容,寫入 1 這個文件,也就是屏幕上。
2. grep hello
grep 這個程序,試圖從 0這個文件中讀取數(shù)據(jù),然后找到包含hello的行,然后把找到的行,寫入到1這個文件中,也就是屏幕上
3. 管道的作用
就是將前一個程序的1綁定到后一個程序的0。
于是,整體才會走通,要不然,cat 的結(jié)果就會打印到屏幕,而不是給了 grep。
作者:庖丁解牛鏈接:https://juejin.cn/post/7081513914840088607