web-dev-qa-db-ja.com

ティーを使用して待機するとスクリプトがハングするのはなぜですか?

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

1
sburke

プロセス置換内のteeは、stdinでeofを取得するか、何らかのエラーが発生するまで終了しません。

また、そのstdinはパイプであるため、書き込み側へのすべてのハンドルが閉じられている場合にのみ、stdinでEOFを取得します。

したがって、元のstdoutとstderrを保存してから、waitの前に、それらを元の状態にリダイレクトする必要があります。 _new>&old_を介してfdsを複製すると、oldfdが閉じられます。

_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_は親によってプロセスを検索します)。 > >(...)に関連するこの落とし穴やその他の落とし穴については、 ここ も参照してください。

4
mosvy