实时反引输出处理

时间:2017-12-05 20:11:27

标签: perl

我不知道这是否可行,但我正在努力通过套接字发送命令的输出,以便在命令运行时它将显示在客户端和服务器计算机上。当我尝试使用反引号时,输出不会保存到变量中,直到命令完成,这对于运行需要很长时间的命令是不利的。

问题:是否有办法逐行扫描输出,说产生另一个过程并让它“观察”变量?

编辑:这是我尝试使用open

open DATA, "pause |" or die "Failed: $!";
while( defined(my $line = <DATA>)){
    chomp($line);
    print "$line\n";
}

我希望在命令完成之前显示输出。

1 个答案:

答案 0 :(得分:6)

你有正确的方法。

my @cmd = ( 'perl', '-e', '$|=1; for (1..5) { print "$_\n"; sleep 1; }' );

open(my $pipe, '-|', @cmd)
   or die("Can't launch child: $!\n");

while (defined( my $line = <$pipe> )) {
    chomp($line);
    print "<$line>\n";
}

当写入STDOUT时,大多数程序在STDOUT是终端时遇到换行符时刷新其输出(&#34;行缓冲&#34;)。当STDOUT不是终端时(&#34;块缓冲&#34;),大多数程序都会回退到阻止输出4 KiB或8 KiB的块。这就是为什么我必须在上面示例中的子程序中使用$|=1;的原因。

使用伪终端而不是管道使用行缓冲可以欺骗使用所述行为的程序。

my @cmd = ( 'unbuffer', 'perl', '-e', 'for (1..5) { print "$_\n"; sleep 1; }' );

open(my $pipe, '-|', @cmd)
   or die("Can't launch child: $!\n");

while (defined( my $line = <$pipe> )) {
    chomp($line);
    print "<$line>\n";
}

IPC::Run提供了一种创建伪终端的本地方法。

use IPC::Run qw( run );

my @cmd = ( 'perl', '-e', 'for (1..5) { print "$_\n"; sleep 1; }' );

my $buf = '';
run(\@cmd, '>pty>', sub {
    $buf .= $_[0];
    while ($buf =~ s/^(.*)\r\n//) {
        print "<$1>\n";
    }
});