我不知道这是否可行,但我正在努力通过套接字发送命令的输出,以便在命令运行时它将显示在客户端和服务器计算机上。当我尝试使用反引号时,输出不会保存到变量中,直到命令完成,这对于运行需要很长时间的命令是不利的。
问题:是否有办法逐行扫描输出,说产生另一个过程并让它“观察”变量?
编辑:这是我尝试使用open
open DATA, "pause |" or die "Failed: $!";
while( defined(my $line = <DATA>)){
chomp($line);
print "$line\n";
}
我希望在命令完成之前显示输出。
答案 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";
}
});