5

サードパーティのプログラムを考えると、同時にどのようになりますか?

  1. stdoutをz.stdoutに書き込みます
  2. stderrをz.stderrに書き込みます
  3. 終了コードを適切に渡す
  4. 両方を正しいインターリーブされた順序でstdoutに書き込みます

これが私が使用しているテストプログラム(delayed_interleaved_stdout_stderr.pl)です:

#!/usr/bin/env perl

use strict;
use warnings;

# fixme: debug, uncomment to force stdout flushing
# use English '-no_match_vars';
# $OUTPUT_AUTOFLUSH = 1;

# use sleeps to simulate delays and test buffering
use Time::HiRes 'sleep';

foreach my $num ( 0..9 ) {
  if ( 0 == $num % 2 ) {
    print STDOUT $num, ":stdout\n";
  }
  else {
    print STDERR $num, ":stderr\n";
  }
  sleep 0.25;
}

これまでのところ、私は次の方法で1,2,3を実行できました。

( set -o pipefail; \
  ( set -o pipefail; delayed_interleaved_stdout_stderr.pl \
    | tee z.stdout; exit $? \
  ) 3>&1 1>&2 2>&3 | tee z.stderr; exit $? \
) 3>&1 1>&2 2>&3

lhunathと友人による関連する回答のおかげで、私はそれを次のように簡略化しました。

delayed_interleaved_stdout_stderr.pl > >(tee z.stdout) 2> >(tee z.stderr >&2)

しかし、正しいインターリーブ順序を取得できませんでした。stderrはすぐに印刷し、(おそらくバッファリングされた)stdoutは最後にすべての印刷を行います。

1:stderr
3:stderr
5:stderr
7:stderr
9:stderr
0:stdout
2:stdout
4:stdout
6:stdout
8:stdout

delayd_interleaved_stdout_stderr.plを単独で実行すると、適切な0〜9の順序で表示されます。stdoutを強制的にフラッシュすることは適切に機能しますが(コメント付きのfixmeセクションを参照)、実際のファイルを変更することはできません。

たぶん私は何か基本的なものが欠けていて、これがまったく可能かどうか疑問に思い始めています:(

4

2 に答える 2

2

要件4はトリッキーなものです。stdoutとstderrのバッファリングロジックはlibc内に埋め込まれているため、これを変更するには、アプリケーションをだまして端末に書き込んでいると見なす必要があります。

unbuffer期待パッケージに付属しているものはあなたのためにこれを行います。警告:端末に書き込んでも、stdoutは行バッファリングされるため、アプリが完全な行を書き込んでいない場合、これは機能しません。

于 2011-08-12T17:01:24.787 に答える
1

サードパーティプログラムにstdoutフラッシュを適用できることを確認しました。これに照らして、私は

delayed_interleaved_stdout_stderr.pl > >(tee z.stdout) 2> >(tee z.stderr >&2)

すべての助けをありがとう!

于 2011-08-15T17:59:29.797 に答える