在进程等待用户输入时将 STDOUT 重定向到文件

Redirect STDOUT to a file while process is waiting for user input

我正在尝试将 STDOUTSTDERR 重定向到日志文件中,但我还想将这些流打印到控制台。我正在使用 Perl,我的代码如下所示:

use Capture::Tiny ':all';

my $stderr, $stdout;

($stdout, $stderr) = capture {
    system($command);
};

print $stdout;
print $stderr;

它可以工作,但如果命令等待用户输入,则程序不会打印 $stdoutSTDOUT,直到按下某个键。有没有办法在需要用户输入之前将 $stdout 打印到 STDOUT?逐行处理就好了。

提前致谢!

嗯,我对 Capture::Tiny 不熟悉,所以这可能不完全相关 - 但一般来说,如果我想处理 STDINSTDOUT and/or STDERR 然后我看向 open (如果它只是一个),或 IPC::Open2 和 [IPC::Open3][1] 打开附加到一个进程的多个文件描述符。

use IPC::Open3;
$pid = open3(\*CHLD_IN, \*CHLD_OUT, \*CHLD_ERR,
                'some cmd and args', 'optarg', ...);

use IPC::Open2;
$pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');

虽然我建议而不是示例 - 您可以使用词法文件句柄:

my($chld_out, $chld_in);
$pid = open2($chld_out, $chld_in, 'some cmd and args');

然后您可以从您的文件句柄读取和写入(不过请记住 - 默认情况下读取将被阻塞)。

您确实需要 close 然后(理想情况下)waitpid 以在您完成后清理流程。

您需要使用 Capture::Tiny's tee 而不是 capture

The tee function works just like capture, except that output is captured as well as passed on to the original STDOUT and STDERR.

只需替换函数调用,您的输出将同时出现在变量和屏幕上。

use Capture::Tiny ':all';

my $stderr, $stdout;

($stdout, $stderr) = tee {
    system($command);
};

我能想到的简单方法:

#! /usr/bin/perl -w

# Using perl one liner as a command here
# which prints a string to STDOUT and STDERR
my $cmd = "perl -e 'print STDOUT \"stdout\n\"; print STDERR \"stderr\n\";'";

my $log = "./test.log";

# using "2>&1" we are redirecting stderr also to stdout
system("$cmd 2>&1 | tee $log");

# Sample run results in both the strings getting printed to console as well as to log file
> perl test.pl
stderr 
stdout

> cat test.log 
stderr
stdout