子プロセスのファイル記述子(fd/0)への書き込み

子プロセスのファイル記述子(fd/0)への書き込み

CentOS 7サンドボックスでファイル記述子を使用しています。この作業の実行中に興味深い状況を発見しました。単純なPHPスクリプトがあるとしましょう。

$step = 4 * 1024;

echo "php started\n";
while (!\feof(\STDIN)) {
    \fwrite(\STDOUT, 'read stdin part: '.\fread(\STDIN, $step)."\n");
}
echo "php finished\n";

bashスクリプトのサブプロセスとしてバックグラウンドで実行し、次の標準入力に渡したいと思います。

php read.php &
phpProcId=$(ps axw -o pid,command | grep 'read' | head -1 | sed -r 's|^\s*([0-9]+)[^0-9]+.*$|\1|g')
echo "phpProcId: $phpProcId"
echo -e "test1\ntest2" >> /proc/$phpProcId/fd/0

ただし、シェル出力は次のようになります。

$ sh box.sh
phpProcId: 2818
$ php started
read stdin part: 
php finished

BashスクリプトがPHPスクリプトの前に操作を完了し、そのデータをPHPサブプロセスに時々渡すことができなかったようです。 fd / 0に書き込んでPHPサブプロセスにデータを渡すにはどうすればよいですか?私はmkfifoについて知っており、この場合は意図的に使用したくありません。

答え1

私はPHPをまったく理解していません。この答えはシェルに関するものです。

  1. ジョブ制御[… ]が無効の場合、明示的なリダイレクトが実行される前に、非同期リストの標準入力は、同じ名前のファイルに割り当てられているかのように処理されます/dev/null。 [… ]

    源泉)

    shシェルなどのスクリプトを実行すると、デフォルトではジョブ制御が無効になります。

    これは、php read.php &一部のfifoで読み取られず、シェルスクリプト全体とstdinを共有しないことを意味します。読み込んでいるファイル(/proc/…/fd/0または他の形式)を正しく識別しても、そのファイルに書き込むことは/dev/nullfifoに書き込むのではなく、writeと同じです。

    もしあなたなら本物必要なものを印刷して/proc/…/fd/0取得するには、likeではなくfifoのように動作することを指す必要があるので、/dev/null合理的なmkfifoデフォルト選択です。

  2. 必要だと思ったら、今使っているこの機器よりも良いことがphpProcIdあります。現在のシェルで実行されている最新のバックグラウンドコマンドの10進プロセスIDに展開されます。しかし、おそらく必要ないかもしれません。なぜなら…phpProcId=$!phpProcId=$(ps …)$!

  3. Bashでは、プロセスに印刷するファイル記述子を作成できます。以下の例では、プロセスは次のようになりますcat -n

    exec 3> >(cat -n)
    # ...
    echo -e "test1\ntest2" >&3
    exec 3>&-
    

    この名前のないfifoの書き込み部分は、私たちが閉じたときに開き、記述子は閉じたときに開きますexecexec 3>&-それなしで:シェルが終了したとき)。一部の子プロセスがその記述子を継承して開いたままでない限り、cat接続後に標準入力がもはや何も接続されなくなるため、最終的に終了します。そうでなくてもecho私たちはcatやめます。

    catスクリプトの終了後、印刷プロンプトの前後にインタラクティブシェルの出力が表示されることがあります。

  4. >(…)通常の形式で作業できませんsh。あなたがタグ付けしましたただしsh box.sh、必要に応じて使用してくださいbash(shebangの使用を検討してください)>(…)

関連情報