Reputation: 103
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
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