2011-08-24 10 views
7

ログファイル内の特定のメッセージを待つスクリプトを実装しようとしています。メッセージがログに記録されたら、スクリプトを続行します。'grep -q'が 'tail -f'で終了しない

は、ここで私はtail -fgrep -qでアウトしようとしていますものです:

# tail -f logfile | grep -q 'Message to continue' 

grepが終了したことがないので、それが継続するメッセージが「ファイルに記録されていても永遠に待ちます。

-fなしでこれを実行すると、正常に動作しているようです。

+0

を、それが尾で何が起こってバッファリングに関連している可能性があります。私はあなたのコマンドを実行すると終了しませんが、もう一度ファイルに書き込むと終了します。 – Kevin

答えて

9

tail -fはファイルを読み込み、後で表示する行は表示されません。終了することはありません(SIGTERMのような信号が送信されない限り)。 grepはこちらのブロック部分ではなく、tail -fです。 grepはパイプが閉じられるまで読み込みますが、tail -fは終了せずパイプを開いたままにしていないためです。


あなたの問題を解決するには、おそらく(ひどく実行する可能性が非常に高いテストしていない)ことになります。-f(フォロー)オプション付きtailが終了していないためだ、と続け

tail -f logfile | while read line; do 
    echo $line | grep -q 'find me to quit' && break; 
done 
+0

詳細については、interrupt、quit、およびその他のシグナルも 'tail -f'を停止します。それにもかかわらず、あなたの診断は基本的に正しいです。 –

+0

@ジョナサン:しかし、私はgrepのマンページを読んだ後に混乱しています。 '-q'で最初の一致の直後に終了するはずですので、op **の例は**動作するはずです。 grepは終了し、パイプからの読書を停止する – knittl

+0

はい、私も...私はそれについて困惑しています。それは私にとって「新しい」行動です。私は '-q'を' -s'と同じものとして覚えています。早期終了は驚くべきことです。私の最高の推測は 'grep'がSIGPIPEを' tail'に送るのを避けていることです。しかし、私はそれを証明していません。 (私は2番目のセンテンスを削除するコメントを編集するつもりでしたが、私はそこに到着しませんでした) –

0

grepに出力します。おそらくperl/pythonではログファイルの行を待つのがより簡単でしょう。

tail -fをPythonサブプロセスモジュールで起動します。 tailからの出力をループで読み込み、必要な行が表示されてからPythonスクリプトを終了します。このソリューションをシェルスクリプトの中に入れます。

Pythonスクリプトは、目的の行が表示されるまでシェルスクリプトをブロックします。

0

私はそれがファイルに第2の書き込みの後、なぜコマンドが終了を説明しているので、私は答えとしてこれを投稿しようと思いました。いくつかの実験をした後

touch xxx 
tail -f xxx | grep -q 'Stop' 
ps -ef |grep 'grep -q' 
# the grep process is there 
echo "Stop" >> xxx 
ps -ef|grep 'grep -q' 
# the grep process actually DID exit 
printf "\n" >> xxx 
# the tail process exits, probably because it receives a signal when it 
# tries to write to a closed pipe 
+1

実際、 'tail -f'はパイプ上に新しい出力を書き込もうとすると' SIGPIPE'を送ります。パイプの読み込みが終了した後です。 'tail -f'の問題は、ファイルの" tail "がパイプへの1回の書き込みに収まること、そして読者が最初のバイトだけを読み込んで終了しても、' SIGPIPE'はその後の書き込みが試みられます。 –

3

、私は問題がbashような方法であると信じてパイプライン内のすべてのプロセスがいくつかの形または形式で終了するのを待ちます。 Cソースのいくつかの360行のプレーンなファイル「QQQ」で

(プログラムのさまざまな連結数回以上)、および「grepの-qリターン」を使用して、その後、私が守っ:

  1. tail -n 300 qqq | grep -q returnはありません一度にほぼ終了する。
  2. tail -n 300 -f qqq | grep -q return終了しません。
  3. tail -n 300 -f qqq | strace -o grep.strace -q return中断されない限り終了しません。 grep.straceファイルで終わる:

    read(0, "#else\n#define _XOPEN_SOURCE 500\n"..., 32768) = 10152 
    close(1)        = 0 
    exit_group(0)       = ? 
    

    これは1の割り込みがtailを殺す前にgrepが終了したことを考えるように私をリードです。それが何かを待っていたら、それはシグナルを受け取ったという兆候があります。

  4. シェルが何をしているかをシミュレートする単純なプログラムですが、待機していないと、物事が終了することが示されます。固定サイズのファイルで

    #define _XOPEN_SOURCE 600 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <stdarg.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <stdio.h> 
    
    static void err_error(const char *fmt, ...) 
    { 
        int errnum = errno; 
        va_list args; 
        va_start(args, fmt); 
        vfprintf(stderr, fmt, args); 
        va_end(args); 
        if (errnum != 0) 
         fprintf(stderr, "%d: %s\n", errnum, strerror(errnum)); 
        exit(1); 
    } 
    
    int main(void) 
    { 
        int p[2]; 
        if (pipe(p) != 0) 
         err_error("Failed to create pipe\n"); 
        pid_t pid; 
        if ((pid = fork()) < 0) 
         err_error("Failed to fork\n"); 
        else if (pid == 0) 
        { 
         char *tail[] = { "tail", "-f", "-n", "300", "qqq", 0 }; 
         dup2(p[1], 1); 
         close(p[0]); 
         close(p[1]); 
         execvp(tail[0], tail); 
         err_error("Failed to exec tail command"); 
        } 
        else 
        { 
         char *grep[] = { "grep", "-q", "return", 0 }; 
         dup2(p[0], 0); 
         close(p[0]); 
         close(p[1]); 
         execvp(grep[0], grep); 
         err_error("Failed to exec grep command"); 
        } 
        err_error("This can't happen!\n"); 
        return -1; 
    } 
    

    tail -fは終了するつもりはない - ので、シェル(bash)がたむろしているようです。

  5. tail -n 300 -f qqq | grep -q returnがハングアップしましたが、もう1つの端末を使用して別の300行をファイルqqqに追加すると、コマンドは終了しました。私はgrepが終了したのでこれを解釈するので、tailが新しいデータをパイプに書き込んだときにSIGPIPEが出て終了し、bashはパイプライン内のすべてのプロセスが停止したことを認識しました。

kshbashの両方で同じ動作が観察されました。これはバグではなく予想される動作であることを示しています。 x86_64マシンでのLinux(RHEL 5)でのテスト。

+4

素敵な分析!興味深いことに、 'grep -q pattern <(tail -f logfile)'はうまくいきます。 –

+0

@KarolyHorvathなぜこれはまだ答えではないのですか? –

3
tail -f logfile | grep --max-count=1 -q 'Message to continue' 

確かに、次の行が読み込まれたときに終了します。直ちに一致する行は読み込まれません。

0

私自身のプロジェクトでこれに対する答えを探していました。 VMware ESXi VM上でGPUを通過したことが正確にいつアクティブになるかをテストしようとしています。同じ質問の複数のバリエーションがどこにでもあります。これはかなり最近です。私はそれを欺くための方法を考え出しました。あなたの興味深い行をログに繰り返し載せれば、次のようになります。

tail -n 1 -f /var/log/vmkernel.log | grep -m 1 IOMMUIntel >>/var/log/ vmkernel.log

これは、一度に1行ずつ、grepは各行を最初に見つけ出してログに追加し、その後すぐに終了します。

よりここに読み、ハッキングpassthough VMwareのようなあなたの場合: http://hackaday.io/project/1071-the-hydra-multiheaded-virtual-computer

関連する問題