2011-08-23 79 views
532

可以在連續流上使用grep嗎?如何'grep'連續流?

我的意思是排序tail -f <file>命令,但輸出grep爲了只保留我感興趣的線。

我試過tail -f <file> | grep pattern但似乎grep只能執行一次tail完成,也就是說永遠不會。

+29

'tail -f file | grep模式「應該工作得很好。 –

+8

生成文件的程序很可能不會刷新其輸出。 –

+0

'tail -f file'的作品(我實時看到新的輸出) –

回答

989

打開grep的行緩衝模式。

tail -f file | grep --line-buffered my_pattern 
+26

這應該是公認的答案。 – Patryk

+2

如果我在運行時尾部旋轉的日誌文件,會發生什麼情況? logrotate能夠旋轉文件嗎? –

+3

@MichaelNiemand你可以使用tail -F file | grep - 線緩衝my_pattern – jcfrei

97

我使用tail -f <file> | grep <pattern>所有的時間。

它會等到grep的刷新,直到沒有完成它(我使用Ubuntu的)。

+3

這可能會持續一段時間,所以儘量不要急躁。 – glglgl

+0

需要多長時間? –

+0

@Matthieu:主要取決於您的操作系統,以及您的操作系統上的緩衝區大小。如果grep每隔幾個小時只匹配一個短的字符串,它將在第一次刷新之前的幾天。 – tripleee

0

是的,這實際上可以正常工作。 Grep和大多數Unix命令一次對一行數據流進行操作。如果匹配,每條從尾部出來的行將被分析並傳遞。

+1

這實際上並不正確。如果'grep'是管道鏈中的最後一個命令,它將按照你的解釋行事。但是,如果它處於中間位置,則會一次緩衝大約8k個輸出。 –

47

我認爲你的問題是,grep使用一些輸出緩衝。嘗試

tail -f file | stdbuf -o0 grep my_pattern 

它將設置grep的輸出緩衝模式爲無緩衝。

+5

這有一個好處,除了'grep'之外,它還可以用於其他許多命令。 –

+4

然而,正如我在玩過更多的遊戲後發現的那樣,有些命令只在連接到tty時刷新輸出,爲此,'debian'(在Debian的'expect-dev'包中)是* king *。所以我會使用unbuffer over stdbuf。 –

+4

@Peter V.Mørch是的,你是對的,unbuffer有時可以在stdbuf不能的地方工作。但我認爲你正試圖找到一個「魔術」程序,它總能解決你的問題,而不是理解你的問題。創建一個虛擬的tty是不相關的任務。 Stdbuf完全符合我們的要求(設置標準輸出緩衝區以提供值),而unbuffer執行大量我們可能不想要的隱藏內容(比較交互式「top」與stdbuf和unbuffer)。並且真的沒有'魔術'解決方案:unbuffer有時也會失敗,例如awk使用不同的緩衝區實現(stdbuf也會失敗)。「 – XzKto

-3

使用awk(另一個偉大的bash實用程序)而不是grep,你沒有行緩衝選項!它將持續不斷地從尾部流式傳輸數據。

這是你如何使用grep

tail -f <file> | grep pattern 

這是你將如何使用AWK

tail -f <file> | awk '/pattern/{print $0}' 
+5

這是不正確的;就像其他大多數標準的Unix工具一樣,Awk開箱即可執行行緩衝。 (此外,'{print $ 0}'是多餘的,因爲打印是條件通過時的默認動作。) – tripleee

4

在大多數情況下,你可以tail -f /var/log/some.log |grep foo,它會工作得很好。

如果您需要在運行日誌文件中使用多裏grep,你會發現,你得到任何輸出,你可能需要將--line-buffered開關貼到您的中間 grep的(一個或多個),像這樣:

tail -f /var/log/some.log | grep --line-buffered foo | grep bar 
1

你可以考慮這個答案,因爲增強。通常我使用

tail -F <fileName> | grep --line-buffered <pattern> -A 3 -B 5 

-F在文件旋轉的情況下更好(如果文件旋轉-f將無法正常工作)

-A和-B對於在模式出現之前和之後獲取行很有用。這些模塊將出現虛線分隔符之間

+1

'grep -C 3 ',如果N相同,則替換-A 和-B 。 –

-1

sed的將是正確的命令(編輯)

tail -n0 -f <file> | sed -n '/search string/p'

,然後,如果你想tail命令退出,一旦你發現了一個特別的字符串:

tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'

顯然,一個bashism:$ BASH PID將是tail命令的進程ID。 sed命令在管道尾部後面,因此sed進程ID將爲$ BASHPID + 1。

+1

在許多情況下,假設系統上啓動的下一個進程('$ BASHPID + 1')將會是錯誤的,並且這對解決緩衝問題沒有任何作用,這可能是OP試圖詢問的問題。特別是,在這裏推薦''sed' over'grep'似乎僅僅是一個(可疑的)偏好問題。 (如果這是你嘗試傳遞的點,你可以用'grep -m 1'來獲得'p; q'的行爲。) – tripleee

2

如果你想找到在整個文件(不只是尾巴)的比賽,你希望它坐等任何新的比賽,這很好地工作:

tail -c +0 -f <file> | grep --line-buffered <pattern> 

-c +0標誌說輸出應該從文件的開頭(+)開始0字節(-c)。