2012-01-31 70 views
15

我想從兩個併發程序(日誌文件的尾部)將輸出捕獲到bash中的一個輸出流中。將兩個併發程序的輸出與bash結合使用

我用這個例子程序來進行測試:

function foo { for i in $(seq 1 10); do echo "program $*"; sleep 1; done } 

現在細

(foo bar & foo baz &) | tee /tmp/output 

但一旦我在添加一個額外的管道混合下列作品它不再起作用:

(foo bar | grep bar & foo baz &) | tee /tmp/output # does't work 

輸出成爲連續的。我可以製作一個包含grep的單獨程序,但我想知道是否有解決方法。

如果有人能解釋爲什麼它不起作用,我會很高興。

回答

7

偉大的問題!這一個讓我難住了一下,但我想我知道發生了什麼。發生了什麼是grep緩衝輸出。所以,如果讓它運行,最終你會看到它全部氾濫。如果你碰巧使用GNU grep嘗試傳遞--line緩衝選項:

(foo bar | grep --line-buffered bar & foo baz &) | tee /tmp/output 

要猜的話,你得注意這是它本質上是什麼,我會說,是grep緩衝更多的輸出,因爲isatty(1)將表明它是而不是寫入TTY(即使您正在通過tee觀看TTY上的輸出)。通過緩衝更多的輸出,它會減少調用write(),並且效率更高。運行grep並觀察終端中的輸出的熟悉行爲是行緩衝的 - 在找到它們時顯示行。該選項強制grep以該模式運行。

請記住,如手冊頁警告,這可能會對grep帶來性能影響。 「即使它是因爲發球區」而造成的「

」 「
+0

」。 grep是*不*寫入tty。 grep正在寫入一個管道,並且tee正在寫入一個tty。 – 2012-01-31 14:52:17

+0

你是對的。我的觀點差 - 我會編輯我的帖子來澄清。 – FatalError 2012-01-31 14:54:02

1

因爲foo bargrep你正在grep來等待foo bar命令的輸出和使用之間的管道的就是爲什麼後巴茲線所有bar行馬上就來。如果你真的想從命令grep的東西,然後定義另一個功能是這樣的:

function foo1 { for i in {1..3}; do echo "program $*" | grep "$*"; sleep 1; done } 

然後執行:

(foo1 bar & foo baz &) | tee /tmp/output 

現在你會發現,輸出如下:

program baz 
program bar 
program baz 
program bar 
program baz 
program bar 
... 
... 
相關問題