水道管が損傷したかどうかはどうすればわかりますか?

水道管が損傷したかどうかはどうすればわかりますか?

1標準出力がパイプにリダイレクトされるPOSIXシェルスクリプトがあります。スクリプトの実行中にある時点でパイプが壊れる可能性があります。

だから私はこれを試しました:

(
  trap "" PIPE  # prevent shell from terminating due to SIGPIPE
  while :; do
    echo trying to write to stdout >&2
    echo writing something to stdout || break
    echo successfully written to stdout >&2
    sleep 1
  done
  echo continuing here after loop >&2
) | sleep 3

以下を印刷します。

trying to write to stdout
successfully written to stdout
trying to write to stdout
successfully written to stdout
trying to write to stdout
successfully written to stdout
trying to write to stdout
sh: 5: echo: echo: I/O error
continuing here after loop

この例では、sleepスクリプトを使用してプログラムの標準出力を置き換えます。 3秒後にsleep終了し、パイプが切断されます。

私たちはstdoutだけをパイピングするので、sleepstderrを使用してその間にいくつかのデバッグメッセージを処理できます。

規制によると、破損したパイプに書き込むとSIGPIPEが発生し、デフォルトの動作はプログラムを終了することです。POSIXsignal.h。そのため、私たちはtrap信号を受け入れて無視しなければなりません。

終了時にsleepパイプが中断され、続いてecho writing something to stdoutSIGPIPEが発生して捕捉(無視)され、echo失敗して|| breakループを終了します。スクリプトは問題なく実行され続けます。

だから上記の例はうまくいきます。明らかな主な欠点は、パイプラインがまだ機能していることを確認するために「stdoutに書き込む」の多くを使用してパイプラインにスパムを送信することです。 「書き込み」パイプecho writing something to stdoutと交換すると、printf ""パイプが損傷してから古いにもかかわらず、SIGPIPEが発生せずにループが続行されます。

どうですか?

ベストアンサー1

スクリプトの実行中にどの時点でパイプが壊れ、いつこのようなことが起こるのかを知りたいです。

パイプに書き込もうとするときにのみこれがわかります。

write()Linuxのマニュアルページによると、リーダーなしでパイプの書き込み側へのすべての呼び出しは、ゼロバイトが書き込まれても信号/エラーを提供する必要があるようです。しかし、私が試しているシェルは、印刷するものがなければシステムコール全体をスキップするので役に立ちません。

ゼロ以外の量のデータを書き込む場合は、書き込み中にある時点でスクリプトがブロックされることがわかります。つまり、リーダがジョブの完了を無視し、パイプバッファがいっぱいになる場合です。

そしてまたコメントでこう言われました。

基本的にシェルスクリプトで選択/ポーリングを使用したいと思います。

...この場合、実際にはシェルから正しいプログラミング言語に切り替える必要があります。または、zselectフロントエンドとして使用できるモジュールがあるZshに切り替えてくださいselect()https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-zsh_002fzselect-Module

select()パイプの読み取り端が閉じたときに見つけるのに役立たないと確信しています。

おすすめ記事