実行中のシェルスクリプトのアクティビティを監視するために名前付きパイプを使用しようとしています。シェルスクリプトは、処理を「開始」したことをパイプに記録します。処理が完了すると、パイプに「Completed」と記録されます。 2 番目のスクリプトは監視を実行し、2 つのメッセージを読み取ります。 2番目のスクリプトが5分以内に「完了」メッセージを受け取らない場合、警告が送信されます。
そこで、2つのプロセス間の通信に名前付きパイプを使用する方法に関するLinux Journalのコードを見つけました。パイプは一度に2つのメッセージを取得し、ループ中にカウンターを表示しようとしますが、「完了」メッセージが表示されると再びゼロにリセットされます。次のメッセージに対してパイプを継続的にポーリングすることを確認するために、タイミングが次に追加されます。しかし、カウンターが増えるのを見ることはできません。パイプから読み出しラインを待っているようです。私が何を間違っているかについての提案はありますか?
#!/bin/bash
pipe=/tmp/testpipe
loopcnt=0
while true
do
echo "count: $loopcnt"
if read line <$pipe; then
if [[ "$line" == 'Started' ]]; then
echo $line
elif [[ "$line" == 'Completed' ]]; then
echo $line
loopcnt=0
fi
fi
((loopcnt=loopcnt+1))
done
ベストアンサー1
パイプの書き込み側が開いていない場合、読み取り側を開くと、書き込みが表示されるまでブロックされます。これは、シェルが独自に実行される前にリダイレクトを設定しようとしたときに発生するため、独自のタイムアウトは役に立ちread
ません。read
-t
それでもパイプに何かを書くとループは続きますが、データを読み取る前に時間が経過しすぎたかどうかを検出することは言うまでもなく、経過した時間を見つけるのに役立ちません。
この問題を解決する最も簡単な方法は、リーダーで読み取り/書き込みモードでパイプを開き、常にライターがあることを確認することです。
たとえば、次のようになります。
#!/bin/bash
pipe=/tmp/testpipe
if ! [[ -p "$pipe" ]]; then
echo "'$pipe' isn't a pipe"
exit 1
fi
exec 3<> "$pipe"
secs=0
timeout=5
while true; do
if read -t 1 -u 3 line; then
echo "read '$line'"
secs=0
else
echo .
fi
if ((++secs >= timeout)); then
echo "no data within $timeout secs"
break
fi
done
echo end.
ただし、$pipe
存在しない場合はexec 3<> "$pipe"
通常のファイルとして生成されますので注意してください。パイプであることを確認するための明示的なテストを実行しても、テストとオープンの間にパイプが削除された可能性があります。これが発生すると、read
ファイルにデータがないため、sはすぐにエラー状態を返します。