*すべて*標準入力がある場合、プログラムが失敗する問題をどのように解決しますか?

*すべて*標準入力がある場合、プログラムが失敗する問題をどのように解決しますか?

たとえば、次は正常に機能します。

/usr/bin/program

いくつかの出力を生成し、結果を取得します。

しかし、私がこう呼んだら:

echo -n | /usr/bin/program

またはこれ

echo -n | bash -c "/usr/bin/program"

またはこれも:

echo -n | bash -c "wc -c; /usr/bin/program"

いくつかの出力ラインを生成して失敗します。プログラムのソースコードにアクセスできないため、これらの動作を引き起こす原因が何であるかさえわかりません。

Pythonスクリプトから呼び出そうとすると、同じ結果が表示されます。

echo | python -c 'from subprocess import call; call("/usr/bin/program", shell=True)'

(「echo」プレフィックスのないバージョンはうまく機能します)

なぜこれが起こるのかわかりません。プログラムがどこで読み取るべきかを明示的に指定しなくても標準入力が開いているので、これは原因ではありません。

この問題を解決する方法はありますか?

編集する:

出力の最後の4行strace- 唯一の他の行は次のとおりです。

# without echo
select(1, [0], NULL, NULL, {0, 0})      = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0})      = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0})      = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0})      = 0 (Timeout)
...

# with echo
select(1, [0], NULL, NULL, {0, 0})      = 1 (in [0], left {0, 0})
write(4, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
write(3, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
exit_group(1)                           = ?

部分的な解決策:

sleep 20 | /usr/bin/program

programstdinで何かが起こるのを待ち、改行やEOFが発生すると終了するようです(selectstrace出力の呼び出しで見ることができます。入力が「実際の」ユーザーから来る場合はタイムアウトします)。したがって、標準入力を開いたまま、標準入力に何も書き込むことなくsleep作業を実行するプログラムが必要です。

答え1

あなたが要求するものを実行するPerlの1行コードは次のとおりです。

perl -e '$SIG{CHLD} = sub{exit 0}; open $fh, "|-", @ARGV or die; sleep 20 while 1;' /usr/bin/program

sleep forever | /usr/bin/programこれは、プログラムの完了を監視し、完了するとすぐに終了することを除いて、本質的にMyth *と同じです。 /usr/bin/programにパラメータが必要な場合は、そのパラメータを行の末尾に追加できます。

*はsleep forever動作しませんが、GNUスリープは永遠に眠りに落ちるでしょうsleep inf

関連情報