简体   繁体   English

Perl - 从外部进程直接输出到stdout(避免缓冲)

[英]Perl - output from external process directly to stdout (avoid buffering)

I have a Perl script that has to wrap a PHP script that produces a lot of output, and takes about half an hour to run. 我有一个Perl脚本,必须包装一个产生大量输出的PHP脚本,并且运行大约需要半个小时。

At moment I'm shelling out with: 我正在炮轰:

print `$command`;

This works in the sense that the PHP script is called, and it does it's job, but, there is no output rendered by Perl until the PHP script finishes half an hour later. 这就是调用PHP脚本的意义上的工作,它完成了它的工作,但是,在PHP脚本完成半小时后,Perl没有输出。

Is there a way I could shell out so that the output from PHP is printed by perl as soon as it receives it? 有没有一种方法可以解决,以便PHP收到它后立即打印出来的输出?

The problem is that Perl's not going to finish reading until the PHP script terminates, and only when it finishes reading will it write. 问题是Perl在PHP脚本终止之前不会完成读取,只有当它完成读取时才会写入。 The backticks operator blocks until the child process exits, and there's no magic to make a read/write loop implicitly. 反引号操作符阻塞,直到子进程退出,并且隐式地进行读/写循环没有魔力。

So you need to write one. 所以你需要写一个。 Try a piped open: 尝试用管道打开:

open my $fh, '-|', $command or die 'Unable to open';
while (<$fh>) {
    print;
}
close $fh;

This should then read each line as the PHP script writes it, and immediately output it. 这应该在PHP脚本写入时读取每一行,并立即输出。 If the PHP script doesn't output in convenient lines and you want to do it with individual characters, you'll need to look into using read to get data from the file handle, and disable output buffering ( $| = 1 ) on stdout for writing it. 如果PHP脚本没有以方便的行输出并且您想要使用单个字符进行输出,则需要使用read来从文件句柄中获取数据,并在stdout上禁用输出缓冲( $| = 1 )写它。

See also http://perldoc.perl.org/perlipc.html#Using-open()-for-IPC 另见http://perldoc.perl.org/perlipc.html#Using-open()-for-IPC

Are you really doing print `$command` ? 你真的在print `$command`吗?

If you are only running a command and not capturing any of its output, simply use system $command . 如果您只运行命令而不捕获其任何输出,只需使用system $command It will write to stdout directly without passing through Perl. 它将直接写入stdout而不通过Perl。

You might want to investigate Capture::Tiny . 您可能想要调查Capture::Tiny IIRC something like this should work: IIRC这样的事情应该有效:

use strict;
use warnings;

use Capture::Tiny qw/tee/;

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

Actually, just using system might be good enough, YMMV. 实际上,只使用system可能就足够了,YMMV。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM