ループ中にbashに影響を与えるためにタイムアウトグローバル変数を使用する方法は?

ループ中にbashに影響を与えるためにタイムアウトグローバル変数を使用する方法は?

whilebash私のスクリプトには、最初と5秒の間隔で異なる操作を実行するループがあります。前のループの完了を許可します。 5秒間隔は、関数によってdo_different設定されたグローバル変数で表されますheartbeat。もう1つの問題は、通常のwhileループが未知の時間内に完了することです(RANDOM以下のスクリプトで簡略化されています)。使用はcronオプションではなく、ランダムなプロセスタイミングでもありません。

成功せずにパイプとプロセスの置き換えを試してみました。スクリプト全体をリファクタリングできます。

#!/bin/bash

function heartbeat {
    do_different=true
    while sleep 5s
    do
        do_different=true
    done
}

heartbeat &

while true
do
    if $do_different
    then
        echo 'Something different'
        do_different=false
        i=0
    else
        # process of random duration; not important
        r=$(( 1 + RANDOM % 3 ))
        sleep "${r}s"
        i=$((i + r))
        echo "$i"
    fi
done

ベストアンサー1

まず、明確でない場合、問題のスクリプトはheartbeat子プロセスで実行されるため、親シェルメモリのシェル変数を変更できないため、失敗します。

OPが望む精神に近いアプローチは次のとおりです。

#!/bin/bash

trap 'do_different=true' USR1

heartbeat() {
    while sleep 5
    do                  # If the parent process has gone away, the child should terminate.
        kill -USR1 "$$"  ||  exit
    done
}

heartbeat &
heartbeat_pid=$!
trap 'kill "$heartbeat_pid"' 0

do_different=true

while true
do
    if "$do_different"
    then
        echo 'Something different'
        do_different=false
        i=0
    else
        # process of random duration; not important
        r=$(( 1 + RANDOM % 3 ))
        sleep "$r"
        i=$((i + r))
        echo "$i"
    fi
done

変更されたプロセスは、heartbeatSIGUSR1シグナルを基本(親)シェルプロセスに送信します。このシグナルとSIGUSR2はユーザー/アプリケーションの使用のために予約されており、システムによって生成されてはなりません。このtrapコマンドを使用すると、シェルスクリプトがシグナルをキャプチャできます。このtrap 'do_different=true' USR1コマンドはSIGUSR1信号(5秒ごとに到着)をキャプチャし、do_different信号が発生したときにフラグを設定するようにシェルに指示します。

heartbeat_pid明らかに、子プロセスのプロセスID(PID)ですheartbeat。このコマンドは、trap 'kill "$heartbeat_pid"' 0スクリプトが終了したことを示す偽信号0が「受信」されたときに何が起こるかを定義します。 Shellがドアに「去った後、家に帰る途中で食料品を取ることを忘れないでください」と書かれたステッカーメモを貼るのと同じだと思います。exitこれは、スクリプトが最後に到達したり、ステートメントを実行したり(このスクリプトでは無限ループであるため、両方は発生しません)、割り込み信号(SIGINT、+によって生成されます)によって終了した場合CtrlCheartbeat

おすすめ記事