使用命名管道

有時你可能希望通過一個程式輸出內容並將其輸入另一個程式,但不能使用標準管道。

ls -l | grep ".log"

你可以簡單地寫一個臨時檔案:

touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt

這適用於大多數應用程式,但是,沒有人會知道 tempFile 做了什麼,如果它包含該目錄中 ls -l 的輸出,有人可能會刪除它。這是命名管道發揮作用的地方:

mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe

myPipe 在技術上是一個檔案(一切都在 Linux 中),所以讓我們在我們剛剛建立管道的空目錄中執行 ls -l

mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l

輸出是:

prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe

注意許可權中的第一個字元,它被列為管道而不是檔案。

現在讓我們做一些很酷的事情。

開啟一個終端,記下目錄(或建立一個目錄,以便清理很容易),並製作一個管道。

mkfifo myPipe

現在讓我們把東西放進菸斗裡。

echo "Hello from the other side" > myPipe

你會注意到這個懸掛,管道的另一側仍然關閉。讓我們開啟管道的另一邊,然後讓這些東西通過。

開啟另一個終端並轉到管道所在的目錄(或者如果你知道它,則將其新增到管道中):

cat < myPipe

你會注意到,輸出 hello from the other side 後,第一個終端中的程式結束,第二個終端中的程式也就完成了。

現在反向執行命令。從 cat < myPipe 開始,然後回覆一些東西。它仍然有效,因為程式會等到一些東西放入管道才終止,因為它知道它必須得到一些東西。

命名管道可用於在終端之間或程式之間移動資訊。

管道很小。一旦完整,寫入器就會阻塞,直到某些讀取器讀取內容,因此你需要在不同的終端中執行讀取器和寫入器,或者在後臺執行一個或另一個:

 ls -l /tmp > myPipe &
 cat < myPipe

使用命名管道的更多示例:

  • 示例 1 - 同一終端/同一 shell 上的所有命令

    $ { ls -l && cat file3; } >mypipe &
    $ cat <mypipe    
    # Output: Prints ls -l data and then prints file3 contents on screen
    
  • 示例 2 - 同一終端/同一 shell 上的所有命令

    $ ls -l >mypipe &
    $ cat file3 >mypipe &
    $ cat <mypipe
    #Output: This prints on screen the contents of mypipe. 
    

    注意顯示 file3 的第一個內容然後顯示 ls -l 資料(LIFO 配置)。

  • 示例 3 - 同一終端/同一 shell 上的所有命令

    $ { pipedata=$(<mypipe) && echo "$pipedata"; } &
    $ ls >mypipe 
    # Output: Prints the output of ls directly on screen 
    

    請注意,變數 $pipedata 不能在主終端/主 shell 中使用,因為使用 & 會呼叫子 shell,而 $pipedata 僅在此子 shell 中可用。

  • 示例 4 - 同一終端/同一 shell 上的所有命令

    $ export pipedata
    $ pipedata=$(<mypipe) &
    $ ls -l *.sh >mypipe
    $ echo "$pipedata"   
    #Output : Prints correctly the contents of mypipe
    

    由於變數的匯出宣告,這會在主 shell 中正確列印 $pipedata 變數的值。由於呼叫背景 shell(&),主終端/主 shell 沒有掛起。