metin görünene kadar "tail -f"


20

Uzaktan bir işe ( jenkinsCI sunucusu ve jenkins-cli.jararaç) başlamamı sağlayan bir komut satırı arayüzü ile bir CI sunucusu var .

İşi başlattıktan tail -fsonra günlük (dağınık komut için üzgünüm):

ssh -t my-jenkins-host.com "tail -f \"/var/lib/jenkins/jobs/$job_name/builds/\`ls -ltr /var/lib/jenkins/jobs/$job_name/builds/ | grep '^l' | tail -n 1|awk '{print \$9}'\`/log\""

İş başarıyla tamamlandıktan sonra, genellikle en az 5 dakika sonra, çıktıda şu satırı alıyorum:

Finished: SUCCESS

Bu noktada kütüğü durdurmayı durdurmanın iyi bir yolu var mı? yani tail_until 'some line' my-file.logkomut gibi mi?

BONUS: SUCCESS eşleştiğinde 0, FAILURE eşleştiğinde 1 ve çözümünüz mac üzerinde çalıştığında dönen bir yanıt sağlayabiliyorsanız ekstra kredi! (ki bsd tabanlı olduğuna inanıyorum)

Yanıtlar:


39

Aradığın çizgiyi gördüğünde bırakılmasını söyleyerek tail -fiçeri girebilirsin sed:

tail -f /path/to/file.log | sed '/^Finished: SUCCESS$/ q'

sedvarsayılan olarak işlediği her satırı çıkarır ve o satırı gördükten sonra çıkar. Bir tailsonraki satırı yazmaya çalıştığında ve çıkış borusunun bozulduğunu gördüğünde işlem durur


Booh evet! mükemmel. ... yani bir şeyle eşleşirsem 0'dan ('BAŞARI' diyelim) ve başka bir şeyle eşleşirsem 1'den (belki 'ARIZA' gibi) çıkmak için bir yol var mı?
aaronstacy

7
@aaronstacy GNU grep kullanıyorsanız, qkomut isteğe bağlı bir çıkış kodu alır. Yani sedkomut şu olurdused '/^Finished: SUCCESS$/ q0; /^Finished: FAILURE$/ q1'
Michael Mrozek

6
Finished: SUCCESSÇıktının son satırı ise bu işe yaramayabilir
lk-

@Michael Mrozek aaaand tabii ben b / c değilim ben friggin mac kullanıyorum
aaronstacy

1
Bu çözümün büyük bir kusuru var: benim durumumda günlük aranan satırla bitiyor. Artık satır yazılmayacak, böylece kuyruk kopmak için bir yol olmadığı için süreç sıkışmış kalacak :(
Phate

6
tail -f my-file.log | grep -qx "Finished: SUCCESS"

-q, yani sessiz, bir eş bulur bulmaz

-xmarkaları grepbütün çizgi maç

İkinci kısım için,

tail -f my-file.log | grep -m 1 "^Finished: " | grep -q "SUCCESS$"

-m <number>grep'e sayı eşleşmelerinden sonra durmasını söyler

ve grep -qçıkış durumu yalnızca satırın sonunda bulunursa 0olurSUCCESS

Tüm çıktıyı görmek istiyorsanız, kullanamazsınız grep -q, ancak yine de

tail -f my-file.log | grep -m 1 "^Finished: "

FAILUREgörüntüleniyorsa çıkış durumunu 1 olarak ayarlayın .


5
grepAslında cevabımda kullandım , ama eğer kullanıyorsa tail -fmuhtemelen dosya çıktısını görmek istiyor; greptüm ara hatları göstermeyecek
Michael Mrozek

4

@ Mrozek'in yorumlarıyla @ Mikel'in cevabında bir varyasyon (Yoruma cevap verirdim ama sanırım henüz yeterli ayrıcalığım yok)

tail -f my-file.log | tee >( grep -qx "Finished: SUCCESS" )

@ Mikel'in çözümünü kullanmanıza ve hala ekranda çıktıyı görmenize izin verir


Buna bir zaman aşımı aralığı ekleyebilir miyiz, örneğin: "60 ila 120 saniye arasında okunmazsa, kuyruğu iptal edin ve kabukta bir hata çıkış kodu verin"?
kiltek

2

Buradaki cevapların hiçbirini beğenmedim, bu yüzden kendi cevaplarımı vermeye karar verdim. Bu bash betiği tüm ölçütleri karşılar ve hata durumunda 1 çıkış için BONUS'u içerir.

#!/bin/bash
while IFS= read -r LOGLINE || [[ -n "$LOGLINE" ]]; do
    printf '%s\n' "$LOGLINE"
    [[ "${LOGLINE}" == "Finished: SUCCESS" ]] && exit 0
    [[ "${LOGLINE}" == "Finished: FAILURE" ]] && exit 1
done < <(timeout 300 tail -f my-file.log)
exit 3

Ayrıca, çıkış kodu 3 ile sonuçlanacak bir zaman aşımı özelliği de vardır. Sisteminizde zaman aşımı komutuna sahip değilseniz, Anthony Thyssen'den timeout.sh komut dosyasını alın:

http://www.ict.griffith.edu.au/anthony/software/timeout.sh

Aşağıdaki yorumlara göre, kaçış karakteri genişletmeyi durdurmak için günlük baskısını güncelledim ve standart bir 'okuma'nın tüm özelliklerini dahil ettim. Tam 'okuma' ayrıntıları için /programming//a/10929511 adresine bakın . EOF kontrolü burada gerekli değildir, ancak eksiksizlik için dahil edilmiştir.


Çok hoş. while IFS= read -r LOGLINEKabuğun satırlarda boşluk bırakmasını önlemek için kullanmayı düşünün tail.
roaima

@roaima: readyalnızca bir değişken olduğunda bölünmez (ve bununla birlikte bir dizi değildir -a), ancak -rgiriş verileri ters eğik çizgi içeriyorsa gerekir . Ancak giriş verileri ters eğik çizgi içeriyorsa, echo "$var"kabuğunuza ve / veya sisteminize bağlı olarak da printf '%s\n' "$line"
bozulabilir

@ dave_thompson_085 "IFS = okuma -r satırı"
roaima

0

İşte neredeyse istediğimi yapan bir python betiği (aşağıdaki uyarılara bakın):

import sys,re

def main():
    re_end = re.compile(sys.argv[1])
    re_fail = re.compile(sys.argv[2]) if len(sys.argv) > 2 else None
    for line in sys.stdin:
        sys.stdout.write(line)
        if re_end.match(line):
            sys.exit(0)
        elif re_fail and re_fail.match(line):
            sys.exit(1)

if __name__ == '__main__': main()

uyarılar:

  • çizgiler geldikçe basılmıyor ... gruplar halinde basılıyorlar ... biraz tamponlama gibi görünüyor

  • Bu benim yol ya da bir şey üzerinde bir komut dosyası olarak yüklemek zorunda kalacak, bu yüzden bu rahatsız edici, ve ben kaygan bir astar tercih ederim :)


güncelleme: tailaynı tamponlamayı yapıyor gibi görünüyor, bu yüzden etrafta çalışmaya değer bir şey olmadığını tahmin ediyorum.
aaronstacy

0

Sorunlarım sedve grepseçenekleri vardı, bu yüzden benimkini yazıyorumone with bash conditions

tail -f screenlog.* | 
while IFS= read line; 
 do 
   echo $line; 
   if [[ $line == *Started\ Application* ]]; 
    then pkill tail; 
   fi; 
done

-1

Sen de dene

 grep -q 'App Started' <(tail -f /var/log/app/app.log)
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.