NASサーバーのsnapraidを自動化するスクリプトを実行しています。これはオンラインで見つけたスクリプトで、Debian9では問題なく動作していました。先週Debian10に更新し、スクリプトを今すぐ更新しましたDebian9にはなかった場所でハングします。問題をteeコマンドとwaitコマンドに絞り込んだと思います。
テスト用にスクリプトを以下のスニペットに短縮しましたが、問題が発生しています。これが、ティーアンドウェイトだと思う理由です。
#!/bin/bash
# location of the snapraid binary
SNAPRAID_BIN="/usr/local/bin/snapraid"
# redirect all output to screen and file
> $TMP_OUTPUT
exec 3>&1 4>&2
# NOTE: Not preferred format but valid: exec &> >(tee -ia "${TMP_OUTPUT}" )
exec > >(tee -a "${TMP_OUTPUT}") 2>&1
# run the snapraid DIFF command
echo "###SnapRAID DIFF [`date`]"
$SNAPRAID_BIN diff
# wait for the above cmd to finish
wait
echo
echo "DIFF finished [`date`]"
また、htopを実行して何が起こっているのかを確認しましたが、snapraidコマンドから作成されたプロセスは終了しません。
待つことはまさにそれがすべきことをしている、待つ、しかしなぜこれは以前にそして今ではなかったのか?
完全なスクリプトはここにあります: https://Pastebin.com/gJqnz875
プロセス置換内のtee
は、stdinでeofを取得するか、何らかのエラーが発生するまで終了しません。
また、そのstdinはパイプであるため、書き込み側へのすべてのハンドルが閉じられている場合にのみ、stdinでEOF
を取得します。
したがって、元のstdoutとstderrを保存してから、wait
の前に、それらを元の状態にリダイレクトする必要があります。 _new>&old
_を介してfdsを複製すると、old
fdが閉じられます。
_exec {out}>&1 {err}>&2
exec > >(tee -a output) 2>&1
...
exec >&$out 2>&$err
wait $(pgrep -P "$$")
_
また、bashの新しいバージョンでのみ、wait
は> >(...)
プロセス置換で実行されているプロセスも待機します。そのため、単にwait
ではなくwait $(pgrep -P "$$")
を使用しました(_pgrep -P
_は親によってプロセスを検索します)。 > >(...)
に関連するこの落とし穴やその他の落とし穴については、 ここ も参照してください。