Bash

如何使用定時全域變數影響 bash while 循環?

  • July 23, 2015

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的初始值,使其在開始時也“做一些不同的事情”。

引用自:https://unix.stackexchange.com/questions/214642