web-dev-qa-db-ja.com

パターンに一致するまでテール-Fを実行します

パターンに一致するまでファイルに対してテール-Fを実行したいと思います。 awkを使用する方法を見つけましたが、私見では私のコマンドは本当にクリーンではありません。問題は、いくつかの制限があるため、私が必要 1行でそれを実行することです。

tail -n +0 -F /tmp/foo | \
awk -W interactive '{if ($1 == "EOF") exit; print} END {system("echo EOF >> /tmp/foo")}'

テールはEOFがファイルに表示されるまでブロックされます。これは非常にうまく機能します。awkの「exit」はすぐには終了しないため、ENDブロックは必須です。awkは前にENDブロックを評価します。終了:ENDブロックは(tailのために)読み取り呼び出しでハングするため、最後に行う必要があるのは、ファイルに別の行を書き込んで、tailを強制的に終了させることです。

誰かがそれを行うためのより良い方法を知っていますか?

22
Sam Alba

これを試して:

sh -c 'tail -n +0 -f /tmp/foo | { sed "/EOF/ q" && kill $$ ;}'

「EOF」文字列が/ tmp/fooに表示されるとすぐに、コマンドライン全体が終了します。

副作用が1つあります。/tmp/fooに何かが書き込まれるまで、テールプロセスは(バックグラウンドで)実行されたままになります。

30
jpetazzo

Tailの--pidオプションを使用すると、Shellが終了するとtailが停止します。テールファイルに余分なものを追加する必要はありません。

sh -c 'tail -n +0 --pid=$$ -f /tmp/foo | { sed "/EOF/ q" && kill $$ ;}'
36
Greg Barrett

私は解決策で結果を出していません:

sh -c 'tail -n +0 -f /tmp/foo | { sed "/EOF/ q" && kill $$ ;}'

ファイルに追加された行がこれ以上ない場合、sedは入力を読み取らないため、バッファーに関連するいくつかの問題があります。だから、もう少し研究して、私はこれを思いついた:

sed '/EOF/q' <(tail -n 0 -f /tmp/foo)

スクリプトは https://Gist.github.com/2377029 にあります

8
harley

これはあなたのために働きますか?

tail -n +0 -F /tmp/foo | sed '/EOF/q'

「EOF」があなたが探しているパターンだと思います。 sedコマンドは、それが見つかると終了します。つまり、tailは、次に書き込むときに終了する必要があります。

ファイルの終わり頃にパターンが見つかった場合、tailがぶらぶらして、ファイルに表示されることのない出力がさらに表示されるのを待つという外部の可能性があると思います。それが本当に懸念される場合は、おそらくそれを殺すように手配することができます-パイプライン全体はsedが終了すると終了します(それが正しい動作ではないと判断する面白いシェルを使用している場合を除く)。


Bashについての不平

恐れられているように、bash(少なくとも、MacOS Xでは、おそらくどこでも)は、tailが終了しても、sedが終了するのを待つ必要があると考えるシェルです。 。時々-私が好きなよりも頻繁に-私は古き良きBourneShellの振る舞いを好みますが、それはそれほど賢くなく、したがってBashよりも間違っていると推測されることが少なくなりました。 dribblerは、メッセージを1秒に1回ドリブルするプログラム(例では「1:Hello」など)で、出力は標準出力になります。 Bashでは、このコマンドシーケンスは、別のウィンドウで「echo pqr >>/tmp/foo」を実行するまでハングします。

date
{ timeout -t 2m dribbler -t -m Hello; echo EOF; } >/tmp/foo &
echo Hi
sleep 1   # Ensure /tmp/foo is created
tail -n +0 -F /tmp/foo | sed '/EOF/q'
date

残念ながら、この動作を制御するオプションがすぐにはわかりません。 shopt lithistを見つけましたが、それはこの問題とは関係ありません。

KornShellのHooray

Korn Shellを使用してそのスクリプトを実行すると、期待どおりに機能することに注意してください。tailが何とか殺されるために潜んでいます。 2番目のdateコマンドが完了した後、そこで機能するのは 'echo pqr >> /tmp/foo'です。

4

これはTclが非常に得意なことです。以下が「tail_until.tcl」の場合、

#!/usr/bin/env tclsh

proc main {filename pattern} {
    set pipe [open "| tail -n +0 -F $filename"]
    set pid [pid $pipe]
    fileevent $pipe readable [list handler $pipe $pattern]
    vwait ::until_found
    catch {exec kill $pid}
}

proc handler {pipe pattern} {
    if {[gets $pipe line] == -1} {
        if {[eof $pipe]} {
            set ::until_found 1
        }
    } else {
        puts $line
        if {[string first $pattern $line] != -1} {
            set ::until_found 1
        }
    }
}

main {*}$argv

次に、tail_until.tcl /tmp/foo EOF

4
glenn jackman

これは、grepの代わりにsedを使用して、tailの出力がstdoutに送られるようにするJonのソリューションの拡張バージョンです。

sed -r '/EOF/q' <( exec tail -n +0 -f /tmp/foo ); kill $! 2> /dev/null

これは、sedがtailの前に作成されるため、$!テールのPIDを保持します

Sh -cソリューションに対するこれの主な利点は、shを強制終了すると、「終了」などの出力に歓迎されない何かが出力されるように見えることです。

2
DanyalBurke
sh -c 'tail -n +0 --pid=$$ -f /tmp/foo | { sed "/EOF/ q" && kill $$ ;}'

ここでの主な問題は$$にあります。コマンドをそのまま実行すると、$$はshではなく、コマンドが実行されている現在のシェルのPIDに設定されます。

キルを機能させるには、kill $$kill \$$に変更する必要があります

その後、tailコマンドに渡された--pid=$$を安全に取り除くことができます。

要約すると、以下は問題なく機能します。

/bin/sh -c 'tail -n 0 -f /tmp/foo | { sed "/EOF/ q" && kill \$$ ;}

オプションで、-nsedに渡して、静かに保つことができます:)

2
Max Horlanchuk

ぶら下がっているtailプロセスも強制終了するには、(Bash)プロセス置換コンテキストでtailコマンドを実行します。これは、バックグラウンドプロセスであるかのように後で強制終了できます。 ( から取得したコード 'tail -f'からパイプラインを介して1行を読み取り、終了する方法は? )。

: > /tmp/foo
grep -m 1 EOF <( exec tail -f /tmp/foo ); kill $! 2> /dev/null
echo EOF > /tmp/foo  # terminal window 2

別の方法として、名前付きパイプを使用することもできます。

(
: > /tmp/foo
rm -f pidfifo
mkfifo pidfifo
sh -c '(tail -n +0 -f /tmp/foo & echo $! > pidfifo) | 
{ sed "/EOF/ q" && kill $(cat pidfifo) && kill $$ ;}'
)

echo EOF > /tmp/foo  # terminal window 2
1
jon

tomcatで使用する準備ができました=

sh -c'tail -f --pid = $$ catalina.out | {grep -i -m 1 "Server startup in" && kill $$;} '

上記のシナリオの場合:

sh -c 'tail -f   --pid=$$ /tmp/foo | { grep -i -m 1 EOF && kill $$ ;}'
1
mayank arora