2016-03-22 2 views
4

私は、ソート可能なタイムスタンプを前に付けた2つのログファイルを持っています。 ログファイルを生成しているプロセスがまだ実行されている間、それらを順番に見たいと思います。これは、状況のかなり忠実なシミュレーションです:最小のバッファリングでソートされたファイルをマージする

slow() { 
    # print stdout at 30bps 
    exec pv -qL 30 
} 
timestamp() { 
    # prefix stdin with a sortable timestamp 
    exec tai64n 
} 

# Simulate two slowly-running batch jobs: 
seq 000 099 | slow | timestamp > seq.1 & 
seq1=$! 
seq 100 199 | slow | timestamp > seq.2 & 
seq2=$! 

# I'd like to see the combined output of those two logs, in timestamp-sorted order 
try1() { 
    # this shows me the output as soon as it's available, 
    # but it's badly interleaved and not necessarily in order 
    tail -f seq.1 --pid=$seq1 & 
    tail -f seq.2 --pid=$seq2 & 
} 
try2() { 
    # this gives the correct output, 
    # but outputs nothing till both jobs have stopped 
    sort -sm <(tail -f seq.1 --pid=$seq1) <(tail -f seq.2 --pid=$seq2) 
} 


try2 
wait 
+0

ああ、あなたはすでに、私にはうってつけの「両方の仕事が止まるまで何もしていない」と言いました。あなたが 'y、x、w、a、b、c、z'のようなデータを持っているなら、正しい順序を得るためにはそれをすべて読む必要があります。非常に近いデータの場合は、タイムスタンプのように、バッファリングシステムを構築することは可能かもしれませんが、yikes!ちなみに大きなQ!がんばろう! – shellter

+2

「チャンク」でバッファリングすることは確かに可能です。そうすれば、ほぼリアルタイムでソートされたログ出力(1分に1回出力ログ)を取得できますが、そのためにウィンドウを選択する必要があり、ログがダンプされますまとめて。 –

+0

2つのストリームは既にソートされているので、システムは実際には各ストリームからバッファを1行だけ必要とします。その時点では、2つのうち小さい方を印刷しても、ソートされた出力を保証することができます。私は確かにそれをPythonで書くことができますが、私は既に発明されたユーティリティを望んでいました。私は実際に 'sort -m'がこのように動作するべきだと考えています... – bukzor

答えて

0

solution using tee(標準出力はまだコンソールに行くようにファイルを書き込むために)teeが不要な遅延を紹介し、解決していないため、動作しません。問題。同様に、tail -f -s 0.01(ポーリングを100/sに変更する)やsplit --filter='sort -sm'のようなコールを使用して小さなバッチをソートする方法もありませんでした。

私のテストコードは、実際にこの機能的に同一のperlのコードを使用して、私はまた、tai64nを持っていない:

shbashでこれを解決するために失敗した後

tai64n() { 
    perl -MTime::HiRes=time -pe ' 
    printf "\@4%015x%x%n", split(/\./,time), $c; print 0 x(25-$c) . " "' 
} 

を、私は私の標準フェイルオーバー、perlを行使

slow() { 
    # print stdout at 30bps 
    pv -qL 30 
} 

tai64n_and_tee() { 
    # prefix stdin with a sortable timestamp and copy to given file 
    perl -MTime::HiRes=time -e ' 
    $_ = shift; 
    open(TEE, "> $_") or die $!; 
    while (<>) { 
     $_ = sprintf("\@4%015x%x%n", split(/\./,time), $c) . 0 x(25-$c) . " $_"; 
     print TEE $_; 
     print $_; 
    } 
    ' "$1" 
} 

# Simulate two slowly-running batch jobs: 
seq 000 099 | slow | tai64n_and_tee seq.1 & 
seq 100 199 | slow | tai64n_and_tee seq.2 & 
wait 

私は既にperlをタイムスタンプに使用していたので、これは便利でした。私はperlとして動作し、tai64nとして動作し、別のperlコールはteeとして動作しますが、それは実際のtai64nで動作する可能性があります。

+0

もし 'tai64n'のためにあなたのperlをサブクラス化すると、プロセスが終了するまで出力が得られず、出力はソートされません。 – bukzor

+0

代わりに上記のbashスクリプトで 'tai64n'を使用すると、出力がひどくインターリーブされます。いくつかの行には2つのタイムスタンプがあり、一部にはタイムスタンプがありません。 – bukzor

+0

さて、私は実際に私のテストでは公開前に 'ティー 'と呼ばれていませんでした。私はあなたの問題を見て、答えを書き直しました。同じループで、このperlコードはタイムスタンプ_and_ copiesを与えられた各ログファイルに追加します。私は 'tee'のperl近似が本当の' tai64n'と動作するのではないかと疑います(実際の 'tee'はここで動作しないのと同じ理由かもしれませんが...) –

関連する問題