proc_open:扩展文件描述符数,使“状态”从Perl脚本反馈(proc_open: Exten

2019-09-16 17:06发布

PHP的proc_open手册指出:

文件描述符数不限于0,1和2 - 你可以指定任何有效的文件描述符,它会被传递给子进程。 这使你的脚本与为“协同进程”运行其他脚本进行互操作。 特别是,这是通过密码短语像PGP,GPG和OpenSSL程序以更安全的方式是有用的。 这也是读通过辅助文件描述符这些程序提供了状态信息是有用的。

发生的事情:我所说的Perl脚本在基于PHP的Web应用程序,并调用传递参数。 我没有未来需要将数据发送到脚本。 通过标准输出[1]我收到来自Perl脚本json_encoded,我在我的PHP应用程序中使用的数据。

我想补充:在Perl脚本通过网站收集进展的信息取决于它的初始调用中传递的参数。 我想发送回PHP应用程序,我可以用它来显示作为一种进度条的文本字符串。

我怎么觉得我应该这样做:我希望轮询(每1-2秒)已设置为“进展”更新的通道。 我会用使用Javascript / jQuery的编写成HTML DIV容器用户查看。 我不认为我应该更关键的“json_encode(数据)”混合“进步”频道的频道,我会再需要破译stdout流。 (这是合乎逻辑的思维,务实?)

我的主要问题:你如何使用额外的“文件描述符?” 我将图像附加信道的设置是简单的,如3 => ...在下面:

$tunnels = array(   
   0 => array('pipe', 'r'),     
   1 => array('pipe', 'w'),    
   2 => array('pipe', 'w'),    
   3 => array('pipe', 'w')        
);

$io = array();
$resource = proc_open("perl file/tomy/perl/code.pl $param1 $param2 $param3", $tunnels, $io);

if(!is_resource($resource)) {
    $error = "No Resource";
}

fclose($io[0]);

$perlOutput = stream_get_contents($io[1]);
$output = json_decode($perlOutput);

$errors = stream_get_contents($io[2]);
print "$errors<p>";

fclose($io[1]);
fclose($io[2]);

$result = proc_close($resource);

if($result != 0) {
    echo "you returned a $result result on proc_close";
}

但是,在Perl脚本我只是写到标准输出,如:

my $json_terms = encode_json(\@terms);
print $json_terms;

如果我的设置附加信道的理解是正确的(上述情况,3 => ...),然后我怎么会写它的Perl脚本内?

谢谢

Answer 1:

假设你要监视一个hello-world程序,其中每一步都写到指定的文件描述符点的进度。

#! /usr/bin/env perl

use warnings;
use strict;

die "Usage: $0 progress-fd\n" unless @ARGV == 1;

my $fd = shift;
open my $progress, ">&=", $fd or die "$0: dup $fd: $!";

# disable buffering on both handles
for ($progress, *STDOUT) {
  select $_;
  $| = 1;
}

my $output = "Hello, world!\n";

while ($output =~ s/^(.)(.*)\z/$2/s) {
  my $next = $1;
  print $next;
  print $progress ".";
  sleep 1;
}

使用bash语法来打开FD 3 /tmp/progress ,并连接到程序是

$ (exec 3>/tmp/progress; ./hello-world 3)
Hello, world!

$ cat /tmp/progress
..............

(这是更有趣的观看现场直播。)

也看到在终端上的点,因为他们的出现,你可以打开你的进步描述符和有效dup2它到实时的标准误差,再次使用bash语法和更多的乐趣。

$ (exec 17>/dev/null; exec 17>&2; ./hello-world 17)
H.e.l.l.o.,. .w.o.r.l.d.!.
.

你当然可以跳过带有额外的步骤

$ (exec 17>&2; ./hello-world 17)

要获得同样的效果。

如果你的Perl程序有错误,如死亡

$ ./hello-world 333
./hello-world: dup 333: Bad file descriptor at ./hello-world line 9.

那么你管在PHP端写端可能有它的特写on-exec标志设置。



Answer 2:

你打开一个新的文件句柄和DUP它文件描述符3:

open STD3, '>&3';
print STDERR "foo\n";
print STD3   "bar\n";

$ perl script.pl 2> file2 3> file3
$ cat file2
foo
$ cat file3
bar

编辑:每格雷格·培根的评论, open STD3, '>&=', 3open STD3, '>&=3'直接打开文件的描述符,像C的fdopen调用,避免dup呼叫,节省您的文件描述符。



文章来源: proc_open: Extending file descriptor numbers to enable “status” feedback from a Perl script