如何使用定時全域變數影響 bash while 循環?
我
while
在腳本中有一個循環,bash
它應該在開始時和每 5 秒間隔做一些不同的事情。允許完成任何先前的循環。5s 間隔由函式do_different
設置的全域變數指示。heartbeat
另一個複雜情況是正常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
首先,如果不是很明顯,問題中的腳本會因為
heartbeat
在子程序中執行而失敗,因此無法更改父 shell 記憶體中的 shell 變數。這是一種更接近 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
修改後
heartbeat
的向主(父)shell 程序發送 SIGUSR1 信號。這和 SIGUSR2 保留給使用者/應用程序使用(並且永遠不應該由系統生成)。該trap
命令允許 shell 腳本擷取信號。該trap 'do_different=true' USR1
命令告訴外殼程序擷取 SIGUSR1 信號(每五秒到達一次)並do_different
在它發生時設置標誌。
heartbeat_pid
,顯然是heartbeat
子程序的程序ID(PID)。該命令trap 'kill "$heartbeat_pid"' 0
定義了在“收到”偽信號 0 時發生的動作,它指的是腳本退出。把這想像成貝殼在門上貼了一張便條,上面寫著“你離開後,記得在回家的路上買雜貨。” 如果腳本到達結尾或執行exit
語句(這兩種情況都不會發生在此腳本中,因為它是一個無限循環),或者如果它被中斷信號終止(SIGINT,由Ctrl
+C
)。這是一個安全網;該heartbeat
程序已被寫入以在父程序消失時終止。
我會使用該
date
實用程序以秒為單位獲取目前時間。#!/bin/bash lastTime=-5 while true do currentTime=$(date +%s) elapsedTime=$((currentTime - lastTime)) if [[ $elapsedTime -ge 5 ]] then echo 'Something different' lastTime=$currentTime i=0 else # process of random duration; not important r=$(( 1 + RANDOM % 3 )) sleep ${r}s i=$((i + r)) echo $i fi done
編輯:更改了
lastTime
的初始值,使其在開始時也“做一些不同的事情”。