透過 FIFO 分配輸出

透過 FIFO 分配輸出

我正在嘗試使用以下方法分發很長的 make 輸出

mkfifo myfifo 
make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo

想法是輸出的子集應該複製到日誌文件,而整個輸出將被重定向到控制台的標準輸出。

一開始它似乎可以工作,但突然停止並保持凍結狀態,直到我按 Ctrl-Z。

進程替換的使用

make 2>&1 | tee >(grep -E "errors|warnings" > errors.log)

不可能,因為 shell 編譯時預設嚴格遵循 POSIX 標準。

platform - ubuntu 風格的發行版。 shell bash 4.2(只有一個可用)

答案1

make 2>&1 | tee myfifo | grep -E "errors|warnings" myfifo > errors.log | cat myfifo
          P1           P2                                              P3

命令沒有什麼意義。它同時啟動這 4 個指令,中間有管道:

  • make 2>&1: stdout 和 stderr 轉到 P1
  • tee myfifo:標準輸入從 P1,標準輸出到 P2。因此tee將輸出寫入 P2myfifo和 P2。
  • grep -E "errors|warnings" myfifo > errors.log: 來自 P2 的標準輸入,但您將檔案名稱 ( myfifo) 傳遞給grep,因此grep不會從其標準輸入讀取。標準輸出轉到errors.log,沒有寫入 P3
  • cat myfifo: 來自 P3 的標準輸入,但再次因為cat給定了檔名,所以它會讀取它。所以兩者同時grep讀取。catmyfifo

由於沒有從 P2 讀取任何內容,因此tee當 P2 已滿時將掛起。也不會顯示已閱讀的cat部分。myfifogrep

make 2>&1 | tee myfifo | grep -e errors -e warnings > errors.log | cat myfifo

我認為更接近你的意思。同樣,P3 沒有被使用,但我們使用 來|並發啟動cat並等待它。

或者你可以這樣做:

make 2>&1 | tee myfifo & grep -e errors -e warnings > errors.log
wait

如果需要更多greps,則需要更多 fifo:

make 2>&1 | tee fifo2grep1 fifo2grep2 &
grep errors fifo2grep1 > errors.log &
grep warnings fifo2grep2 > warnings.log
wait

在支援 的系統上/dev/fd/x,您還可以執行以下操作:

make 2>&1 | { tee /dev/fd/3 | grep -e errors -e warnings 3>&-; } 3>&1

(這通常是進程替換在支援它的 shell 中所做的事情)。

如果是 2grep秒,則變為:

make 2>&1 |
 {
   {
     tee /dev/fd/3 /dev/fd/4 |
       grep errors > errors.log 3>&- 4>&-
   } 4>&1 |
     grep warnings > warnings.log 3>&-
 } 3>&1

答案2

之後grep -E "errors|warnings" myfifo > errors.log管道不再包含資料。因此cat myfifo從管道讀取的下一個命令將被阻止。

如果我正確理解您的問題,您希望將所有訊息列印到 stdout,並將所有錯誤和警告訊息重定向到errors.log.所以如果你想使用管道,請使用兩個:

 mkfifo pipe1 pipe2 
 make 2>&1 | tee pipe1 pipe2 | grep -E "errors|warnings" pipe1 > errors.log | cat pipe2

相關內容