0

I have a while loop in a bash script which should do something different at the beginning and at every 5 second interval. Any previous loop is allowed to complete. The 5s interval is indicated by the do_different global variable set by the heartbeat function. An additional complication is that a normal while loop completes in an unknown amount of time (simplified with RANDOM in below script). Using cron is not an option, neither is timing the random process.

I already unsuccessfully tried using a pipe as well as process substitution. The whole script may be re-factored.

#!/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
Serge Stroobandt
  • 28,495
  • 9
  • 107
  • 102
  • I think set -m is what you are looking for... http://stackoverflow.com/questions/1455695/forking-multi-threaded-processes-bash – kpie Jul 08 '15 at 18:18

1 Answers1

0

The problem is that while loops are executed in a new subshell with their own copy of the global variables. There are many possible workarounds. Grouping all commands into the subshell is what worked here for me.

#!/bin/bash

t_lastdue=$(date --date='5seconds ago' +%s)

while true
do
    t_now=$(date +%s)
    t_elapsed=$((t_now - t_lastdue))
    if [ $t_elapsed -ge 5 ]
    then
        echo 'Something different'
        t_lastdue=$((t_lastdue + 5))
        i=0
    else
        # process of random duration; not important
        r=$(( 1 + RANDOM % 3 ))
        sleep "${r}s"
        i=$((i + r))
        echo "$i"
    fi
done
Serge Stroobandt
  • 28,495
  • 9
  • 107
  • 102