stdout 到 file1,stderr 到 file2,两者都正确交错到 stdout 和 file
给定一个第三方程序,如何同时:
- 将 stdout 写入 z.stdout
- 将 stderr 写入 z.stderr
- 传递退出代码
- 以正确的交错顺序将两者正确写入到 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:
- write stdout to z.stdout
- write stderr to z.stderr
- pass exit codes appropriately
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要求 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.我确认我可以对第三方程序强制执行标准输出刷新。鉴于此,我将
感谢所有帮助!
I confirmed I can enforce stdout flushing for the third-party programs. In light of this, I'm going with
Thanks for all help!