7

PHPのproc_openマニュアルには、次のように記載されています。

ファイル記述子番号は0、1、および2に限定されません。有効なファイル記述子番号を指定すると、子プロセスに渡されます。これにより、スクリプトを「コプロセス」として実行される他のスクリプトと相互運用できます。特に、これは、パスフレーズをPGP、GPG、opensslなどのプログラムに安全な方法で渡す場合に役立ちます。また、補助ファイル記述子でこれらのプログラムによって提供されるステータス情報を読み取る場合にも役立ちます。

何が起こるか: PHPベースのWebアプリケーションでPerlスクリプトを呼び出し、その呼び出しでパラメーターを渡します。今後、スクリプトにデータを送信する必要はありません。stdout [1]を介して、PHPアプリケーションで使用するjson_encodedデータをPerlスクリプトから受け取ります。

追加したいこと: Perlスクリプトは、最初の呼び出しで渡されたパラメーターに応じて情報を収集するWebサイトを進行しています。一種のプログレスバーとして表示するために使用できるテキスト文字列をPHPアプリケーションに送り返したいと思います。

どのようにすべきか:その「プログレッション」アップデート用に設定されたチャネルを(1〜2秒ごとに)ポーリングすることを期待します。Javascript / jQueryを使用して、ユーザーが表示できるようにhtmldivコンテナーに書き込みます。stdoutストリームを解読する必要があるため、「progress」チャネルをより重要な「json_encode(data)」チャネルと混合する必要はないと思います。(これは論理的で実用的ですか?)

私の主な質問:追加の「ファイル記述子」 をどのように使用しますか?以下の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スクリプトでは、次のようにstdoutに書き込むだけです。

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

追加のチャネルを設定するという私の理解が正しければ(上記の3 => ...)、Perlスクリプト内でどのようにチャネルに書き込むのでしょうか?

ありがとう

4

2 に答える 2

2

新しいファイルハンドルを開き、ファイル記述子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

編集: Greg Baconのコメントに従って、open STD3, '>&=', 3またはopen STD3, '>&=3'Cの呼び出しのようにファイル記述子を直接開き、fdopen呼び出しを回避しdupてファイル記述子を保存します。

于 2012-04-24T20:16:58.240 に答える
2

各ステップが指定されたファイル記述子に書き込まれたドットである 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)
こんにちは世界!

$ 猫/tmp/進行状況
…………

(生で見たほうが面白いです。)

端末に表示されるドットも表示するには、進行状況記述子を開いて、効果的dup2に標準エラーに出力することができます。これも bash 構文を使用して、リアルタイムでより楽しくできます。

$ (exec 17>/dev/null; exec 17>&2; ./hello-world 17)
こんにちは、。。世界!。
.

もちろん、余分なステップをスキップすることもできます

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

同じ効果が得られます。

Perl プログラムが次のようなエラーで終了した場合

$ ./ハローワールド 333
./hello-world: dup 333: ./hello-world 行 9 のファイル記述子が正しくありません。

次に、PHP 側のパイプの書き込み側には、おそらく close-on-exec フラグが設定されています。

于 2012-04-24T20:51:11.633 に答える