由于设计限制,我不能使用像 Capture::Tiny 这样的解决方案。我需要尽快将输出转发到缓冲变量,并且需要能够区分 STDOUT 和 STDERR。理想情况下,针对外部命令的解决方案应该与 system 函数基本相同,只是可以捕获 STDOUT 和 STDERR 而不是打印它们。
我的代码应该实现以下功能:
- 保存旧的 STDOUT/STDERR 文件句柄。
- 为 STDOUT 和 STDERR 创建新的文件句柄。
- 将所有输出重定向到这里。
- 执行一些操作。
- 恢复旧的文件句柄。
- 处理已捕获的输出,例如打印它。
#!/usr/bin/perl -CSDAL
use warnings;
use strict;
use IPC::Open3;
#use IPC::Run3;
# Save old filehandles
open(my $oldout, ">&STDOUT") or die "Can't dup STDOUT: $!";
open(my $olderr, ">&STDERR") or die "Can't dup STDERR: $!";
my $buffer = "";
close(STDOUT);
close(STDERR);
open(STDOUT, '>', \$buffer) or die "Can't redirect STDOUT: $!";
*STDERR = *STDOUT; # In this example STDOUT and STDERR are printed to the same buffer.
print "1: Test\n";
#run3 ["date"], undef, \*STDOUT, \*STDERR; # This doesn't work as expected
my $pid = open3("<&STDIN", ">&STDOUT", ">&STDERR", "date");
waitpid($pid,0); # Nor does this.
print STDERR "2: Test\n";
open(STDOUT, ">&", $oldout) or die "Can't dup \$oldout: $!";
open(STDERR, ">&", $olderr) or die "Can't dup \$olderr: $!";
print "Restored!\n";
print $buffer;
预期结果:
Restored!
1: Test
Mo 25. Mär 13:44:53 CET 2019
2: Test
实际结果:
Restored!
1: Test
2: Test
open3
无法处理字符串缓冲区句柄?为什么不在open3
调用中使用常规文件句柄呢? - Håkon Hæglandeval
我可以获取 run3 语句的错误信息:Error: run3(): Invalid argument redirecting STDOUT at /root/test_io.pl line 25.
然而这并没有帮助我。如果不重新分配STDOUT
和STDERR
,代码将按预期工作。我有点不知所措。 - K.A.B.