我的意思是使用以下命令來grep帶有標題的“zsh”行程。但是這個命令只顯示了標題然后就退出了。grep沒有跑。我可以通過其他方式完成這項任務,但我想了解這里發生了什么。有趣的是,如果像lsreplaces這樣的其他命令,管道會按預期作業ps -e。事實上,即使有ps(沒有-e),管道也能正常作業。如果head被另一個管道替換,管道也可以作業grep。看起來,在這個管道中ps -e,head和之間有一些有趣的互動。tee有什么解釋嗎?我在 MacOS-iterm2 和 zsh 中運行了這些命令。謝謝。
ps -e|tee >(head -n 1) >(grep "zsh") >/dev/null
上面的命令產生以下不正確的輸出:只顯示標題,grep 沒有運行。
PID TTY TIME CMD
可以通過以下命令生成正確的輸出:
ps -e|awk 'FNR==1{print};/zsh/{print}'
PID TTY TIME CMD
1658 ttys000 0:00.30 -zsh
2817 ttys001 0:00.49 /bin/zsh -i
12890 ttys002 0:00.26 -zsh
13332 ttys003 0:00.23 -zsh
13469 ttys004 0:00.19 /bin/zsh -i
更新:問題確實tee出在 MacOS 附帶的問題上。作為@OndrejK。在下面的評論中指出,tee來自 GNU 按預期作業。
uj5u.com熱心網友回復:
我認為 Ondrej K. 在評論中指出了這一點:head正在讀取它從 接收的第一行tee,然后退出,因此當tee嘗試將第二行寫入該管道時,它會收到一個錯誤(可能實際上是一個 SIGPIPE 信號)并退出而沒有寫剩下的ps's輸出。
我能夠在 macOS 和 Raspbian 下重現這個問題,同時使用 zsh 和 bash 作為我的 shell。我能夠通過替換head為讀取(但不輸出)其余輸入的內容來獲得完整的輸出tee。這是一個例子:
% ps -e|tee >(head -n 1) >(grep "zsh") >/dev/null
PID TTY TIME CMD
% ps -e|tee >(head -n 1; cat>/dev/null) >(grep "zsh") >/dev/null
PID TTY TIME CMD
13127 pts/0 00:00:00 zsh
13353 pts/0 00:00:00 zsh
% ps -e|tee >(sed -n '1p') >(grep "zsh") >/dev/null
PID TTY TIME CMD
13127 pts/0 00:00:00 zsh
在上面的第二個版本中,添加cat>/dev/nullafterhead讓它在head退出后消耗(并丟棄)其余的輸入。在第三個中,sed -n '1p'讀取其整個輸入,但只列印第一行。
請注意,這里的結果將取決于緩沖區大小和各種事件的時間等因素,因此它可能在不同環境之間不一致,甚至在明顯一致的條件下隨機變化。我懷疑它使用ps(沒有-e選項)的原因是它沒有產生足夠的輸出來觸發問題:tee可能能夠從ps之前轉發整個輸出head到退出。
編輯:至少在我的環境中,head退出后添加延遲可以防止問題:
% ps -e|tee >(head -n 1; sleep 1) >(grep "zsh") >/dev/null
PID TTY TIME CMD
8002 pts/0 00:00:00 zsh
8164 pts/0 00:00:00 zsh
這意味著它是時間限制的,而不是緩沖區限制的。但是如果輸出ps足夠大,它會在某個時候遇到緩沖區限制,并且無論插入什么延遲,輸出都會被截斷。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/479315.html
