Search code examples
linuxbashshelluntil-loop

Until loop not terminating or holding incremented variable's value


Why is this loop not breaking(ending due to if statement) or using the newly incremented value of $c variable? Tried c=expr $c + 1 with and without " double quote.

export c=1; ssh auser@someserver "until [[ 1 -eq 2 ]]; do echo \"Value of 'c' == $c\"; c=`expr $c + 1`; echo \"$c - Incremented value: `expr $c + 1`\"; if [[ $c -gt 5 ]]; then break; fi; sleep 2 ; done;"

or

$ export c=1; ssh root@$CHEF_SERVER \
> "until [[ 1 -eq 2 ]]; do \
>   echo \"Value of 'c' == $c\"; c=`expr $c + 1`; \
>   echo \"$c - Incremented value: `expr $c + 1`\"; \
>   if [[ $c -gt 5 ]]; then break; fi; \
>   sleep 2; \
>   echo; \
> done;"

Output is infinte: I had to ^c it.

Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Value of 'c' == 1
1 - Incremented value: 2
Killed by signal 2.

Solution

  • You need to understand that shell variables needs to be properly escaped before using them in conditionals or assignments inside ssh under double quotes. Not doing so will let the variables expand even before the commands are executed over the remote machine. So in your case, no matter if you increment c or not the variable is expanded and condition remains always as below in the remote machine.

    if [[ 1 -gt 5 ]]; then
        break
    fi
    

    Also expr is pretty much outdated, use a traditional C style loop increment using ((..)) as and escape all the invocations of variable inside to defer the variable expansion

    ssh root@$CHEF_SERVER "
    until [[ 1 -eq 2 ]]; do
        ((c = c+1))
        echo "Incremented value: \$c"
        if [[ \$c -gt 5 ]]; then
            break
        fi
        sleep 2
    done"