Linux服務器中最強大的shell操作符之一就是pipe。在本文中,我們將看到常規pipe和命名pipe的工作原理,如何使用它們以及它們之間的區別。
豎條符號|表示pipe。由于pipe的存在,你可以將一個命令的輸出作為輸入,并將其送至另一個命令。換句話說,pipe是一種重定向的形式,在Linux中用于將一個程序的輸出送到另一個程序中進行進一步處理。
pipe或未命名的pipe命令的語法是任意兩個命令之間的|字符。
command1 | command2 | … | commandN
為了了解pipe是如何工作的,讓我們來看看下面的例子。
假設我們有一個目錄,里面有很多不同類型的文件,我們想知道這個目錄中某一類型的文件有多少。我們想知道這個目錄中有多少個特定類型的文件。我們可以使用ls很容易地得到一個文件列表。
ls
為了區分我們感興趣的文件類型,我們將使用grep。我們要找到名字或文件擴展名中含有 “txt “的文件。
我們將使用特殊的shell字符|來引導ls的輸出到grep。
ls | grep txt
ls的輸出沒有被發送到終端窗口。因此,結果并沒有顯示在屏幕上,而是被重定向到grep命令的輸入端。我們在上面看到的輸出來自grep,它是這個鏈中的最后一條命令。
現在,讓我們開始擴展我們的鏈。我們可以通過添加wc命令來計算 “txt “文件。我們將在wc中使用-l選項(行數)。
ls | grep txt | wc -l
grep不再是鏈中的最后一條命令,所以我們看不到它的輸出。grep的輸出被輸入到wc命令中,我們在終端窗口中看到的輸出來自wc。我們在終端窗口中看到的輸出來自于wc。wc報告說,在目錄中有2個文件 “txt”。
顧名思義,這些都是有名字的pipe。普通pipe和命名pipe的一個關鍵區別是,命名pipe在文件系統中是存在的。也就是說,它們以文件的形式出現。
命名pipe是一種使用被賦予特定名稱的pipe將信息從一個計算機進程傳遞到另一個計算機進程的方法。命名pipe也被稱為FifO,即First In, First Out的意思。
你可以通過文件權限部分的p位來判斷一個文件是否是一個命名的pipe。
ls -l mypipe
命名pipe實際上是文件系統本身的文件。與標準pipe不同,命名pipe是作為文件系統的一部分被訪問的,就像其他類型的文件一樣。
命名pipe的內容駐留在內存中,而不是寫入磁盤。只有當pipe的兩端都被打開時,它才會被傳遞。而且在pipe的另一端被打開并讀取之前,你可以多次向pipe寫入內容。通過使用命名pipe,你可以建立一個進程,在這個進程中,一個進程向一個pipe寫入,另一個進程從一個pipe讀取,而不必太過擔心嘗試時間或仔細協調它們的交互。
為了了解命名pipe是如何工作的,讓我們來看看下面的例子。首先,讓我們創建一個命名pipe。
mkfifo mypipe
現在讓我們用這個pipe來消耗消息。
tail -f mypipe
打開另一個終端窗口,給這個pipe寫一條信息。
echo “hi” >> mypipe
現在在第一個窗口中你可以看到打印出來的 “hi”。
因為是pipe,消息已經被消耗掉了,如果我們檢查文件大小,可以看到還是0。
ls -l mypipe
由于命名的pipe只是一個文件,要刪除一個文件,我們可以使用rm命令。因此,要刪除我們在前面的例子中創建的pipe,我們將運行以下命令
rm mypipe
何時使用常規或命名pipe
使用常規pipe而不是命名pipe取決于我們要尋找的特性。其中一些可以是持久性,雙向通信,有一個文件名,創建一個過濾器,以及限制訪問權限等等。
例如,如果我們想多次過濾一個命令的輸出,使用匿名pipe似乎是最合適的選擇。另一方面,如果我們需要一個文件名,而又不想把數據存儲在磁盤上,我們要找的是一個命名pipe。