サブシェルから親シェルにstdout / stderrを読み込む

サブシェルから親シェルにstdout / stderrを読み込む

シェルスクリプトで名前付きパイプを使用して外部プロセスXのstdinに書きたいのですが、別の名前付きパイプから現在の端末にstdout / stderrを送信したいと思います。

外部プロセスXはPIPEINを介してstdinを受信し、対応するstdout / stderrをPIPEOUTに送信します。

tail -f $(tail -F PIPEOUT) &  # (1) this is completely wrong, need help here

for i; do
    echo "${i}" > PIPEIN  # send stdin to X
done

echo "[stdin end]" > PIPEIN  # signal that we are done writing (there might be a better way lol)

したがって、上記のスクリプトでは、しばらく実行されているプロセスXを起動しました。ただし、上記のスクリプトを実行すると、いくつかの標準入力をXに送信し、PIPEOUTを使用してプロセスXの標準出力を読み取ろうとしました。

上記でやりたいことは、stdinをXに送信する前にPIPEOUTの読み取りを設定して、Xのすべてのstdout / stderrがキャプチャされたことを確認することです。問題は、いくつかのバックグラウンドプロセス(PIPEOUTから読み取るtailまたはcat)を実行し、そのstdioを現在の端末に送信する方法がわからないことです。

私が何を言っているのか知っている人はいますか?私が正しく覚えていたら、(1)とマークされた行を修正し、何らかの方法でPIPEOUTで読み取ることができる読み取りをバックグラウンドで設定し、そのstdioを現在の端末/ ttyに何らかの方法で送信する必要がありました。

答え1

あなたが何をしたいのか明確ではありませんtail -f $(tail -F PIPEOUT) &。これはtail -fingファイルです。うん結果 tail -F、通常終了しません。私の仮定は、どのくらい時間がかかってもパイプを通過するすべてを出力したいということです。

justの問題tail -fは、何でも出力する前にファイルの終わりを見つける必要があるということですが、パイプではこれは決して起こりません。あなたはできますtail代わりに明確な出発点を提示する-n +x、開始行を選択します(最初から開始、1からインデックス付き)。tail -n 1 -f fooそれから得ることができるすべてを表示しますfoo

tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
    echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN

ただし、echo > fooその行を作成した後はfooが閉じられることに注意してください。もう一方の端のコマンドはそれを処理する必要があります。例が人為的に作成され、実際の入力が他の場所から来た場合は無視できます。


また参考にしてくださいプロセスtailは終了しません。- そして、パイプラインを通してもっと多くが出てくる可能性を常に期待しています。おそらく、シェルのジョブ制御を使用して直接明示的に終了する必要があります。出力に完了したことを示すパターンがある場合は、以下を見つけることができます。retail(「正規表現の後に来る」)便利 -retail -n +1 -f -u REGEX PIPEOUT一致する行が表示されたら終了しますREGEX(免責事項として、私はretailこの目的のために数年前にこの記事を書きました)

答え2

書き込みのためにPIPEINを一度だけ開くと、2秒遅れてもプログラムは終了します。

mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
    echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN

fifo を何度も開くと、fifo を読んでいる人が fifo が閉じていると考えることができるので、他のリーダーが fifo からデータを読み取るまで作成者は一時停止します。

したがって、保存された賭けは、PIPEINを一度だけ開くことです。それ以外の場合は、プログラムが停止していることがわかります。

関連情報