web-dev-qa-db-ja.com

テキストが表示されるまで「tail -f」

リモートでジョブを開始できるコマンドラインインターフェイスを備えたCIサーバーを持っています(jenkins CIサーバーとjenkins-cli.jarツール)。

仕事を始めた後、私はtail -fログ(乱雑なコマンドでは申し訳ありません):

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\""

ジョブが正常に完了した後、通常は少なくとも5分後、出力に次の行が表示されます。

Finished: SUCCESS

この時点でログのテーリングを停止する良い方法はありますか?つまり、tail_until 'some line' my-file.logコマンド?

BONUS:SUCCESSが一致したときに0を返し、FAILUREが一致したときに1を返す回答を提供できる場合、追加のクレジット、およびあなたの解決策はMacで動作します! (私はbsdベースであると私は信じています)

20
aaronstacy

tail -fsedに追加して、検索している行が見つかると終了するように指示します。

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

sedは、デフォルトで処理する各行を出力し、その行を検出した後に終了します。 tailプロセスは、次の行を書き込もうとして、出力パイプが壊れていることを検出すると停止します

39
Michael Mrozek
tail -f my-file.log | grep -qx "Finished: SUCCESS"

-q、静かを意味し、一致が見つかるとすぐに終了します

-xgrepを行全体に一致させます

2番目の部分については、

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

-m <number>numberが一致した後にgrepを停止するように指示します

また、grep -qの終了ステータスは、SUCCESSが行末にある場合にのみ0になります。

すべての出力を表示したい場合、grep -qは使用できませんが、それでも実行できます

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

FAILUREが表示された場合、終了ステータスを1に設定する以外はすべて実行します。

6
Mikel

@Mrozekのコメントを含む@Mikelの回答のバリエーション(コメントには返信しましたが、まだ十分な権限がないと思います)

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

@Mikelのソリューションを使用しても、画面に出力が表示される

4
Chirlo

私はここで答えが好きではなかったので、自分で答えることに決めました。このbashスクリプトはすべての基準を満たし、失敗時に1を終了するためのボーナスが含まれています。

#!/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

また、終了コードが3になるタイムアウト機能も含まれています。システムにタイムアウトコマンドがない場合は、Anthony Thyssenからtimeout.shスクリプトを入手してください。

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

以下のコメントに従って、エスケープ文字の展開を停止するようにログ印刷を更新し、標準の「読み取り」のすべての機能を含めました。完全な「読み取り」の詳細については、 https://stackoverflow.com/a/10929511 を参照してください。 EOFチェックはここでは必要ありませんが、完全を期すために含まれています。

4
verayth

sedgrepとそれらのオプションに問題があったので、私はone with bash conditions

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

あなたもやってみます

 grep -q 'App Started' <(tail -f /var/log/app/app.log)
0
Deano

ここにpythonスクリプト--ほぼが私がやりたいことをします(以下の警告を参照))です:

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()

警告:

  • 入ってくると線は印刷されません...それらはグループで印刷されます...いくつかのバッファリングが起こっているようです

  • 私はこれを自分のパスまたは何かにスクリプトとしてインストールする必要があるので、それは不便であり、滑らかなワンライナーを好みます:)

0
aaronstacy