
我正在嘗試使用以下方法分發很長的 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 轉到 P1tee myfifo
:標準輸入從 P1,標準輸出到 P2。因此tee
將輸出寫入 P2myfifo
和 P2。grep -E "errors|warnings" myfifo > errors.log
: 來自 P2 的標準輸入,但您將檔案名稱 (myfifo
) 傳遞給grep
,因此grep
不會從其標準輸入讀取。標準輸出轉到errors.log
,沒有寫入 P3cat myfifo
: 來自 P3 的標準輸入,但再次因為cat
給定了檔名,所以它會讀取它。所以兩者同時grep
讀取。cat
myfifo
由於沒有從 P2 讀取任何內容,因此tee
當 P2 已滿時將掛起。也不會顯示已閱讀的cat
部分。myfifo
grep
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
如果需要更多grep
s,則需要更多 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