Belirli bir dize gözlenene kadar komutun çıktısını "izle" ve sonra çık


29

Belirli bir dize gözlenene ve sonra çıkana kadar komutun çıktısını programlı olarak izlemenin bir yolunu arıyorum. Bu, bu soruya çok benzer , ancak bir dosya eklemek yerine, bir komutu 'kuyruklamak' istiyorum.

Gibi bir şey:

izle -n1 my_cmd | grep -m 1 "Dize Arıyorum"

(Ama bu benim için çalışmıyor.)

GÜNCELLEME: 'my_cmd' nin sürekli metin çıktılamadığını, ancak dize bulunana kadar tekrar tekrar aranması gerektiğini açıklığa kavuşturmam gerekiyor (bu yüzden 'watch' komutunu düşündüm). Bu bakımdan, 'my_cmd' gibi diğer birçok unix komutları gibidir: ps, ls, lsof, last, etc.


tail -fBir dosya çıktısının yanı sıra bir program çıktısının mümkün olduğunu düşünürdüm ... Yanlış mıyım?
Joanis

@Joanis. Haklısın, ama benim durumumda 'my_cmd' sürekli olarak çıktı üretmiyor ve tekrar tekrar çağırılması gerekiyor (çoğu komut gibi: ps, ls, lsof, etc)
gdw2 4

Yanıtlar:


41

Bir döngü kullanın:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

Yerine :, kullanabilirsiniz sleep 1CPU kolaylaştırmak için (veya 0.2).

Döngü, grep komutun çıktısındaki dizeyi bulana kadar çalışır. -m 1"bir eşleşme yeterli" anlamına gelir; yani grep, ilk eşleşmeyi bulduktan sonra aramayı durdurur.

Aynı zamanda grep -qilk eşleşmeyi bulduktan sonra, ancak eşleşen çizgiyi yazdırmadan da çıkacak olanı kullanabilirsiniz .


bu komutun açıklaması memnuniyetle karşılanacaktır.
Mark W,

@MarkW: Güncelleme yapıldı.
choroba

başka biri grep -q, başka bir seçenek olduğunu belirtti. grep, dizgiyi bulduktan sonra çıkar.
Güneş,

Bu komutun, istenen veya istenen olmayabilir söz konusu komutu tekrar tekrar çalıştıracağını unutmayın.
adrien

1
@A__: OP'de "Güncelleme" başlığı altında belirtildiği gibi arzu edilir.
choroba

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! komut boru hattının çıkış kodunu olumsuzlar
  • grep -m 1 dize bulunduğunda çıkar
  • watch -e herhangi bir hata oluştuğunda döner

Ancak bu, şimdiye kadar atılmış olan eşleşen çizgiyi görüntülemek için geliştirilebilir.


Ayrıntılı açıklama için teşekkürler, ama benim için işe yaramıyor. Benim watchkomut (CentOS) yoktur -ebayrağı (ki gerçekten önemli gerekir). Daha da önemlisi, dize bulunduğunda, saat çalışmaya devam eder ve çıkmaz. O zaman görünüyor grep -mçıkışlar, sadece öldürür çıkar my_cmd, ancak watch.
gdw2

Hayır, sorun değil !, "-e" bayrağı, komutun 0'dan farklı bir hata kodu olduğunda izlemeyi bırakmak için kullanılır; Her neyse, bilmek güzel, benim Ubuntu 11.10 kurulumumda her şey yolunda. Ayrıca bazen çok güncel olmayan komut satırı araçlarıyla ilgili Mac OSX ile ilgili sorun yaşıyorum ve daha güncel yazılımlar elde etmek için şimdiye kadar mac portları kullanıyorum.
matematik

Bu, model bulunursa durur, ancak bu gerçekleşene kadar herhangi bir çıktı göstermez
Mark

Bunun teeiçin istihdam edebilirsiniz , ancak bu yanıltıcı bir yeni hat tanıtıyor, şu an nasıl dolaştırılacağımı bilmiyorum:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
matematik

Evet, bu benim için işe yaramadı. watchdize bulunduğunda dikkatlice izlemeyi durdurur, ancak siz bir tuşa basana kadar çıkmaz. Çok yakın.
mlissner

8

Sürekli stdout'a yazılan bir programa sahip olanlar için, yapmanız gereken tek şey 'single match' seçeneğiyle aşındırmak. Grep eşleşen dizgiyi bulduktan sonra, grep'e aktarılan işlemdeki stdout'u kapatan çıkacaktır. Bu olay , işlem tekrar yazdığı sürece programın doğal olarak düzgün bir şekilde çıkmasına neden olmalıdır .

Olacak olan şey, grep çıktıktan sonra kapalı stdout'a yazmaya çalıştığında, işlem bir SİGPEPE alacak. İşte ping ile bir örnek, aksi takdirde süresiz çalışacak:

$ ping superuser.com | grep -m 1 "icmp_seq"

Bu komut ilk başarılı 'pong' ile eşleşecek ve daha sonra pingstdout'a yazmayı denediğinde bir dahaki seferden çıkacaktır .


Ancak,

Sürecin tekrar stdout'a yazacağı ve bu nedenle bir SIGPIPE'nin yükseltilmesine neden olamayacağı her zaman garanti edilemez (örneğin, bir günlük dosyasını tararken bu olabilir). Bu senaryo için bulabildiğim en iyi çözüm bir dosyaya yazmak; Lütfen geliştirebileceğinizi düşünüyorsanız yorum yapın:

$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }

Bunu yıkmak:

  1. tail -f log_file & echo $! > pid- bir dosyayı yazar, işlemi arka plana ekler ve PID ( $!) dosyasını bir dosyaya kaydeder. PID'yi bir değişkene dışa aktarmayı denedim, ancak görünen o ki burada ve PID tekrar kullanıldığında bir yarış durumu var.
  2. { ... ;}- grup hep birlikte (tasarruf ve değişkenleri yeniden yardımcı olur zaman, ama o kısmı çalışma almak mümkün değildi) geçerli bağlamı tutarken çıktı grep boru can bu yüzden bu komutları
  3. | - boru sol tarafının stdout'unu sağ tarafın stdinine
  4. grep -m1 "find_me" - hedef dizgeyi bulun
  5. && kill -9 $(cat pid)- Force kill (SIGKILL) , eşleşen dizeyi bulduktan sonra çıktıktan sonrakitail süreç grep
  6. && rm pid - yarattığımız dosyayı kaldır

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

Eğer taildesteklemiyorsa +1fsözdizimi, deneyin tail -f -n +1. ( -n +1Baştan başlamasını söyler; tail -fvarsayılan olarak, son 10 satırlık çıktıyla başlar.)


Lütfen soru güncellememe bakın.
gdw2

0

Program çağrılarınızın sonucunu bir dosyaya ekleyin. Sonra tail -fbu dosya. Bu şekilde çalışması gerekir ... Umarım.

Bu programı aramayı yeniden başlattığınızda, dosyayı silmeniz veya aradığınız şeyle hemen eşleşmemesi için biraz anlamsızca eklemeniz gerekir.

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.