一个基本的方法是使用管道打开,你open 一个管道到一个被分叉的进程。然后来自子级的STDOUT 通过管道传输到父级的文件句柄,或者父级管道传输到它的STDIN。
use warnings;
use strict;
my @cmd = qw(ls -l .); # your command
my $pid = open(my $fh, '-|', @cmd) // die "Can't open pipe from @cmd: $!";
while (<$fh>) {
print;
}
close $fh or die "Error closing pipe from @cmd: $!";
这样,父级在发出时会收到子级的STDOUT 权限。†
您可以对错误检查进行更多操作,请参阅手册页 close 和 $? in perlvar。此外,为SIGPIPE 安装处理程序,请参阅perlipc 和%SIG in perlvar。
有些模块可以更轻松地运行外部命令,尤其是检查错误。但是Capture::Tiny 和IPC::Run3 使用文件来传输外部程序的流。
另一方面,IPC::Run 为您提供更多的控制权和权力。
要执行代码"... each time some data is read from the child" 使用回调
use warnings;
use strict;
use IPC::Run qw(run);
my @cmd = (
'perl',
'-le',
'STDOUT->autoflush(1); for (qw( abc def ghi )) { print; sleep 1; }'
);
run \@cmd, '>', sub { print $_[0] };
一旦你使用IPC::Run,更多的可能,包括更好的错误查询、为进程设置伪 tty 等。如果关于如何管理进程的需求变得更加复杂,那么使用模块。
感谢 ikegami 提供 cmets,包括演示 @cmd。
† 为了证明父母收到孩子的STDOUT,因为它被发出,使用一个发出延迟输出的命令。例如,代替上面的ls -l 使用
my @cmd = (
'perl',
'-le',
'STDOUT->autoflush(1); for (qw( abc def ghi )) { print; sleep 1; }'
);
这个 Perl 单行打印单词间隔一秒,这就是它们在屏幕上结束的方式。