stdout 到 file1,stderr 到 file2,两者都正确交错到 stdout 和 file

发布于 2024-11-29 02:29:55 字数 1570 浏览 0 评论 0原文

给定一个第三方程序,如何同时:

  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

单独运行delayed_interleaved_stdout_stderr.pl 会以正确的0-9 顺序显示。强制 stdout 刷新工作正常(请参阅注释的修复部分),但我将无法修改实际文件。

也许我错过了一些基本的东西,我开始怀疑这是否可能:(

Given a third-party program, how would one simultaneously:

  1. write stdout to z.stdout
  2. write stderr to z.stderr
  3. pass exit codes appropriately
  4. write both in correct interleaved order to stdout

Here's the test program (delayed_interleaved_stdout_stderr.pl) I've been using:

#!/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;
}

So far I've been able to do 1,2,3 with:

( 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

Thanks to a related answer by lhunath and a friend, I simplified it to:

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

However, I haven't been able to get correct interleaved order. stderr prints immediately and the (presumably buffered) stdout all prints at the end.

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

Running delayed_interleaved_stdout_stderr.pl by itself displays in the proper 0-9 order. Forcing stdout to flush works appropriately (see commented fixme section), but I won't be able to modify the real files.

Maybe I'm missing something basic and I'm beginning to wonder if this is possible at all :(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

潦草背影 2024-12-06 02:29:55

要求 4 是最棘手的一项。 stdout 和 stderr 的缓冲逻辑隐藏在 libc 中,要更改它,您需要欺骗应用程序,使其认为它正在写入终端。

Expect 包附带的 unbuffer 将为您完成此操作。警告:即使写入终端,标准输出也是行缓冲的,因此如果您的应用程序没有写入整行,那么这将不起作用。

Requirement 4 is the tricky one. The buffering logic for stdout and stderr is buried within libc, and to change it you need to fool the application to think it's writing to a terminal.

unbuffer which comes with the expect package will do this for you. Caveat: even writing to a terminal, stdout is line-buffered, so if your app isn't writing full lines then this won't work.

浅笑轻吟梦一曲 2024-12-06 02:29:55

我确认我可以对第三方程序强制执行标准输出刷新。鉴于此,我将

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

感谢所有帮助!

I confirmed I can enforce stdout flushing for the third-party programs. In light of this, I'm going with

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

Thanks for all help!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文