2017-02-05 7 views
0

これらは、私のテストファイルです:処理stdoutとstderr:間違った順序

std-test.sh:

#!/bin/bash 
for i in {0..20} 
do 
    number=$RANDOM 
    let "number %= 10" 
    if [ $number -le 6 ] 
    then 
     echo $i; 
    else 
     echo $i 1>&2; 
    fi 
done 

process.sh:

#!/bin/bash 

while read line; do 
    [[ $1 = "err" ]] && echo "$(date +%s%3N) $line" >> stderr; 
    [[ $1 = "out" ]] && echo "$(date +%s%3N) $line" >> stdout; 
done 

std-test.shは、その行番号を含む20行を作成し、 process.shはパイプされたときに別のコマンド出力を読み取ることができますが、0123に保存します引数としてerrが渡された場合は、outが渡された場合はstdoutになります。全体をテストするコマンドは、 ./std-test.sh 2> >(./process.sh err) > >(./process.sh out)hereから取得)です。次のように私のテスト出力は、次のとおり

stdout:

1486297129986 0 
1486297129987 1 
1486297129988 2 
1486297129988 3 
1486297129989 4 
1486297129990 6 
1486297129991 7 
1486297129991 8 
1486297129992 9 
1486297129993 10 
1486297129993 11 
1486297129994 12 
1486297129995 14 
1486297129995 17 
1486297129996 18 

stderr:

1486297129986 5 
1486297129987 13 
1486297129987 15 
1486297129988 16 
1486297129989 19 
1486297129990 20 

I出力を解析しようとしたとき、私はstderrstdoutの順序は完全に台無しにされていることを、実現しました。 stderrの5がstdoutの1の前に来るのはなぜですか?または13の直後ですか?私がここで作ったミスは何ですか?どうすれば解決できますか?

編集#1:私は直接ファイルへのパイプの標準エラー出力と標準出力できたけど、process.shは、リモートサーバに結果をカールします。ファイルに保存することはPOCのようなものです。

編集#2:私は、プログラムでドッカーログをタイムスタンプして処理しようとしています。

+1

フラッシングの問題だと思います。 stderrとstdoutはエコー後に直接フラッシュされないかもしれません。 stderrは常にバッファがいっぱいになったときにだけフラッシュされますが、stderrは常に即座にフラッシュされるようです。たとえば、https://www.turnkeylinux.org/blog/unix-buffering –

答えて

0

更新:OPが実際にタイムスタンプとドッキングウィンドウコンテナ内で実行中のアプリケーションからの出力をログに記録しようとしていた表示されたコメントから

docker logs -tすでにこれを実行しており、仕事に最適なツールです。


オリジナルの答え:おそらく

あなたはそれが、彼らがしている時間は、実際に発生した処理されていない時間で各行をタイムスタンプしているので?

このコマンドを実行すると3つのプロセスが起動されますが、それらのプロセスはすべて並列に実行されるわけではありません。

プロセスは本当に並行して実行されているわけではなく、カーネルが気になるたびに先取りされる可能性があります。 stdoutはより長い/より多くの行を処理するので、より優先され、後で再開されます。これはタイムスタンプを説明するものです。

本当にタイムラインが必要なのは何ですか?単にラインの間で注文したいのですか、本当のタイムスタンプが本当に欲しいですか?

編集:@Sven Festersenがコメントに指摘したように、それはまたstdout is buffered when piped by defaultである可能性があります。

+0

を参照してください。本当のタイムスタンプが本当に必要です。プログラムでドッキング・コンテナを実行し、ログをキャッチしてデータベースに格納します。フォーマットされたタイムスタンプの横にあるすべての行を表示し、すべてのstderr出力を赤色に着色するWebインタフェースを使用して問合せできます。 –

+0

@BenjaminLaibその場合、ドッカーが既に提供しているものを活用したいかもしれません。 'docker logs --timestamps'を使って、タイムスタンプを付けられたdockerからアプリケーションのログを取得することができます。それはおそらくあなたが望むものであり、おそらくより堅牢です。 – ffledgling

+0

本当にありがとう!このオプションが存在するかどうかはわかりませんでした。 –

関連する問題