連続ポーリング名前付き(FIFO)パイプ

連続ポーリング名前付き(FIFO)パイプ

実行中のシェルスクリプトのアクティビティを監視するために名前付きパイプを使用しようとしています。シェルスクリプトは、処理を「開始」したことをパイプに記録します。処理が完了すると、パイプに「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はすぐにエラー状態を返します。

関連情報