我需要(想要吗?)使用Minion队列从Web应用程序中生成缓慢的进程。
该过程-GLPK求解器-可以运行很长时间,但会生成进度输出。
我想捕获该输出,并将其写入到某个地方(数据库?日志文件?),以便可以在Web应用程序中以状态更新的形式向用户播放该输出。
有可能吗?我不知道(因此也没有代码)。
我正在探索Capture::Tiny-它的简单性很好,但是我无法确定它是否可以在写入时跟踪写入事件。
答案 0 :(得分:4)
一种基本方法是使用管道打开,在该管道上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的评论,包括演示@cmd
。
†要演示父级在发出子级STDOUT
时收到它,请使用命令来延迟输出。例如,代替上面的ls -l
使用
my @cmd = (
'perl',
'-le',
'STDOUT->autoflush(1); for (qw( abc def ghi )) { print; sleep 1; }'
);
这种Perl单线打印的单词相隔一秒,这就是它们在屏幕上的显示方式。