Carter
Carter

Reputation: 103

Counter resets every time my while loops?

I'm writing a script to restart a process if the associated screen isn't found after 5 checks:

f=0
while true; do(
    for s in server1 server2 server3; do(
            if ! screen -ls|grep -q "$s"; then(
                    f=$(($f + 1))
                    #Here, f is always 1 more than the value
                    #I set at the beginning of the script
                    echo "$s missed $f heartbeats"
            )else(
                    f=0
            )fi

            if [ "$f" -ge 5 ]; then(
                    echo "`date`: $s down, starting"
                    /path/to/start/script
            )fi
    )done
sleep 1
#f is 0 here
)done

f is being set back to the initial value after each iteration of the while loop, even though I don't set f within the loop. How can I make my counter persist?

Upvotes: 0

Views: 135

Answers (1)

chepner
chepner

Reputation: 531165

The unnecessary parentheses you use to enclose the bodies of each loop and if statement form a subshell, and any changes made to a variable in a subshell are local to that shell and vanish when the subshell exits.

f=0
while true; do
    for s in server1 server2 server3; do
        if ! screen -ls|grep -q "$s"; then
            f=$(($f + 1))
            echo "$s missed $f heartbeats"
        else
            f=0
        fi
        if [ "$f" -ge 5 ]; then
            echo "`date`: $s down, starting"
            /path/to/start/script
        fi
    done
    sleep 1
done

From the SHELL GRAMMAR section of the bash man page (emphasis mine):

(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below). Variable assignments and builtin commands that affect the shell's environment do not remain in effect after the command completes. The return status is the exit status of list.

Upvotes: 4

Related Questions