Sürekli bir akış nasıl 'grep' edilir?


729

grepSürekli bir akışta kullanmak mümkün mü ?

Demek istediğim, bir tür tail -f <file>komut, ama grepsadece beni ilgilendiren satırları tutmak için çıktıda.

Denedim tail -f <file> | grep patternama grepsadece tailbittikten sonra idam edilebilir gibi görünüyor , yani asla.


9
Büyük olasılıkla dosyayı üreten program çıktısını temizlemiyor.
Steve-o

tail -f fileçalışır (Yeni çıktıyı gerçek zamanlı olarak görüyorum)
Matthieu Napoli


@Luc gerçekten, bunu düşünmemiştim
Matthieu Napoli

Giriş akışınızda yeni satır olmayabilir mi? Eğer öyleyse grep devam etmeyecektir.
Lynch

Yanıtlar:


1326

grepBSD grep (FreeBSD, Mac OS X vb.) Kullanırken satır arabelleğe alma modunu açın

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

GNU grep (hemen hemen her Linux'ta kullanılır) için bunu yapmanız gerekmez, çünkü varsayılan olarak temizlenir (SmartOS, AIX veya QNX gibi diğer Unix beğenileri için YMMV).


3
@MichaelNiemand kuyruk -F dosyasını kullanabilirsiniz | grep --line-buffered my_pattern
jcfrei

47
@MichaelGoldshteyn Sakin ol. İnsanlar "grep line arabelleğe alınmış" google bu sayfa buldukları ve onlar için bir sorun tam olarak soru olarak ortaya olmayabilir bir sorun çözer çünkü onu yok.
raine

4
Buraya çıktısını grep etmeye çalıştım strace. Olmadan, --line-bufferedişe yaramaz.
sjas

5
@MichaelGoldshteyn (ve onun yorumun upvoters): Her zaman bu sorun vardı tail -f | grepve --line-bufferedbu benim için çözer (Ubuntu 14.04 üzerinde, GNU grep versiyon 2.16). "Stdout tty ise satır arabelleğe alma" mantığı nerede uygulanır? In git.savannah.gnu.org/cgit/grep.git/tree/src/grep.c , line_bufferedsadece argüman ayrıştırıcı tarafından ayarlanır.
Aasmund Eldhuset

8
@MichaelGoldshteyn BSD grep kullanarak macOS kullanıyorum ve --line-bufferedçıktı almıyorum . Bununla birlikte, testten sonra, GNU grep'in tarif ettiğiniz şeyi yaptığı anlaşılıyor. Pek çok şey gibi, Unix, platformunuzun uygulamasına bağlıdır. Soru platformu belirtmedi beri senin istihbaratın yanlış gibi görünüyor - BSD grep için kod gözden geçirilmesi ve GNU grep karşılaştırarak sonra, davranış kesinlikle --line-tamponlu seçeneği ile kontrol edilir. Sadece varsayılan olarak sadece GNU grep temizlenir.
Richard Waite

118

Her tail -f <file> | grep <pattern>zaman kullanıyorum.

Grep yıkana kadar bekleyecek, bitene kadar değil (Ubuntu kullanıyorum).


4
Bu oldukça uzun sürebilir, bu yüzden sabırsız olmamaya çalışın.
glglgl

Yaklaşık olarak ne kadar sürebilir?
Matthieu Napoli

@Matthieu: Esas olarak ne için grep'e ve işletim sisteminizde arabelleklerin büyüklüğüne bağlıdır. Grep sadece birkaç saatte bir kısa bir dizeyle eşleşirse, ilk yıkamadan günler önce olacaktır.
Üçlü

13
Kuyruk çıktı arabelleğe alma kullanmıyor - grep kullanıyor.
XzKto

7
Hayır, grep, bu yanıtta olduğu gibi, çıktı bir tty cihazına giderken çıktı tamponlaması yapmaz. Çizgi tamponlama yapar! Bu doğru cevaptır ve kabul edilen cevap olmalıdır. Daha fazla ayrıntı için şu anda kabul edilen ( yanlış ) yanıtla ilgili uzun yorumuma bakın.
Michael Goldshteyn

67

Ben senin sorunun grep bazı çıktı tamponlama kullanıyor olduğunu düşünüyorum. Deneyin

tail -f file | stdbuf -o0 grep my_pattern

grep'in çıktı tamponlama modunu arabelleksiz olarak ayarlayacaktır.


7
Ve bunun avantajı, diğer birçok komut için de kullanılabilmesidir grep.
Peter V.Mørch

4
Bununla birlikte, onunla daha fazla oynadıktan sonra keşfettiğim gibi, bazı komutlar çıktılarını yalnızca bir tty'ye bağlandığında yıkar ve bunun için unbuffer( expect-devdebian paketinde) kraldır . Bu yüzden stdbuf üzerinde tampon çözücü kullanırdım.
Peter V.Mørch

5
@Peter V. Mørch Evet, haklısın, tampon çözücü bazen stdbuf'un çalışamayacağı yerlerde çalışabilir. Ama bence sorununuzu anlamak yerine her zaman sorunlarınızı çözecek bir 'sihirli' program bulmaya çalışıyorsunuz. Sanal bir tty oluşturmak ilgisiz bir görevdir. Stdbuf tam olarak istediğimizi yapar (standart çıktı tamponunu değer vermek için ayarlar), unbuffer istemeyeceğimiz çok fazla gizli şey yapar ( topstdbuf ve unbuffer ile etkileşimli karşılaştır ). Ve gerçekten 'sihirli' bir çözüm yok: tampon çözücü bazen de başarısız oluyor, örneğin awk farklı tampon uygulaması kullanıyor (stdbuf da başarısız olacak).
XzKto

2
"Ama bence sorununuzu anlamak yerine her zaman sorununuzu çözecek bir 'sihirli' program bulmaya çalışıyorsunuz." - Bence haklısın! ;-)
Peter V. Mørch


13

Tüm dosyada (sadece kuyrukta değil) eşleşme bulmak istiyorsanız ve herhangi bir yeni eşleşme için oturmasını ve beklemesini istiyorsanız, bu iyi çalışır:

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

-c +0Bayrak çıkışı başlaması gerektiğini söyler 0bayt ( -cbaşından (itibaren) +dosyasının).


12

Çoğu durumda, yapabilirsiniz tail -f /var/log/some.log |grep foove iyi çalışır.

Çalışan bir günlük dosyasında birden çok açılır pencere kullanmanız gerekiyorsa ve çıktı almadığınızı fark ederseniz, --line-bufferedanahtarı şu şekilde orta grep (ler) inize yapıştırmanız gerekebilir :

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

7

bu yanıtı bir geliştirme olarak düşünebilirsiniz .. genellikle kullanıyorum

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

-F dosya döndürme durumunda daha iyidir (-f dosya döndürülürse düzgün çalışmaz)

-A ve -B, desen oluşumundan hemen önce ve sonra çizgiler elde etmek için faydalıdır. Bu bloklar kesikli çizgi ayırıcılar arasında görünecektir.

Ama benim için aşağıdakileri yapmayı tercih ederim

tail -F <file> | less

akışlı günlüklerin içinde arama yapmak istiyorsanız bu çok kullanışlıdır. Yani geri dönüp derinlemesine bak


4
grep -C 3 <pattern>, N aynıysa -A <N> ve -B <N> yerine geçer.
AKS

6

Kimse bunun için her zamanki go-to teklif görmedim:

less +F <file>
ctrl + c
/<search term>
<enter>
shift + f

Bunu tercih ederim, çünkü ctrl + cdosyayı her zaman durdurmak ve içinde gezinmek için kullanabilirsiniz ve ardından shift + fcanlı, akışlı aramaya geri dönmek için düğmesine basın.


4

sed daha iyi bir seçim olurdu ( akış editörü)

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

ve sonra tail komutunun belirli bir dizeyi bulduğunuzda çıkmasını istiyorsanız:

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

Açıkçası bir bashizm: $ BASHPID kuyruk komutunun işlem kimliği olacaktır. Sed komutu borudaki kuyruktan sonra gelir, bu nedenle sed işlem kimliği $ BASHPID + 1 olacaktır.


1
Sistemde ( $BASHPID+1) başlatılan bir sonraki işlemin sizin olacağı varsayımı birçok durumda yanlıştır ve bu muhtemelen OP'nin sormaya çalıştığı şey olan tamponlama sorununu çözmek için hiçbir şey yapmaz. Özellikle, tavsiye sedüzerine grepburada (şüpheli) tercih sadece bir madde gibi görünüyor. (Bu, teslim etmeye çalıştığınız p;qgrep -m 1
noktaysa

Çalışır, sed komutu hazır olur olmaz her satırı yazdırır, grep komutu ile --line-bufferedvermedi. Eksi 1'i içtenlikle anlamıyorum.
MUY Belçika

Şimdiye kadar, tamponlamanın grep ile ilgili sorun olduğu tespit edilmiştir . Sed kullanarak satır arabelleğe almayı işlemek için özel bir işlem gerekmez , bu varsayılan davranıştır, dolayısıyla kelime akışı vurgusu . Ve doğru, $ BASHPID + 1'in doğru pid olacağının garantisi yoktur , ancak pid tahsisi sıralı olduğundan ve borulu komuta hemen ardından bir pid atandığından , tamamen olasıdır.
Christian Herr

1

Evet, bu gerçekten işe yarayacak. Grepve çoğu Unix komutu akışlarda her seferinde bir satır çalışır. Kuyruktan çıkan her çizgi analiz edilir ve eşleşirse iletilir.


2
Aslında bu doğru değil. Eğer grepboru zincirindeki son komut açıklamak olarak, bu hareket edecektir. Ancak, eğer ortadaysa, bir seferde 8k çıkış tamponlayacaktır.
Mahmoud Al-Qudsi

1

Bu tek komut benim için çalışıyor (Suse):

mail-srv:/var/log # tail -f /var/log/mail.info |grep --line-buffered LOGIN  >> logins_to_mail

posta hizmetine giriş toplama


-1

kesinlikle başarılı olamayacaksın

tail -f /var/log/foo.log |grep --line-buffered string2search

kuyruk için bir takma ad olarak "colortail" kullandığınızda, örneğin. bashta

alias tail='colortail -n 30'

tail isan diğer adı gibi bir çıktı verirse, tür takma adına göre kontrol edebilirsiniz colortail -n 30. o zaman suçlu var :)

Çözüm:

takma adı kaldır

unalias tail

bu komutla 'gerçek' kuyruk ikili dosyasını kullandığınızdan emin olun

type tail

hangi gibi bir şey çıktı gerekir:

tail is /usr/bin/tail

ve sonra komutunu çalıştırabilirsin

tail -f foo.log |grep --line-buffered something

İyi şanslar.


-4

Çizgi tamponlu seçeneği olmayan grep yerine awk (başka bir büyük bash yardımcı programı) kullanın! Verilerinizi sürekli olarak kuyruktan aktaracaktır.

grep'i böyle kullanıyorsun

tail -f <file> | grep pattern

Awk'i böyle kullanırsınız

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

6
Bu doğru değil; Kutudan çıkan awk, diğer çoğu standart Unix aracı gibi satır arabelleğe alma gerçekleştirir. (Dahası, {print $0}bir koşul geçtiğinde yazdırma varsayılan eylem olduğu için gereksizdir.)
üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.