1

I'm trying to get my head around this. I have a basic Bash script:

#!/bin/bash

do_exit=0

while [ "$do_exit" == 0 ] ; do

        echo $do_exit

        do_exit=1

done

This works. However, when I want to set do_exit=1 inside an if condition:

#!/bin/bash

do_exit=0

while [ "$do_exit" == 0 ] ; do

    free=`free -m | grep Mem | awk '{print $4}'`

    if [ "$free" -gt 0 ]
    then

        echo $do_exit

        do_exit=1

    fi & sleep 5;

done

$do_exit is ALWAYS 0 ... so never exists. What am I doing wrong? I'm have the same issue with "breaking" and "exit 0" when I want to kill te script - it just carries on!)

I must be misunderstanding how variables work in Bash? In Perl (my normal programing language), you can set variables anywhere (with the exception of explicitly setting them in a function)

9
  • 2
    what is the value of free? are you sure it's getting set to something -gt 0? is the echo firing? & sleep 5 should probably be && sleep 5 ... but I'm also wondering about the placement of this clause (ie, when exactly do you want the script to sleep?); as alluded to in Bayou's answer ... a single & says to spawn a sub-process and put said process in the background in which case the assignment (performed in a sub-process) is not seen by the parent process
    – markp-fuso
    Commented Feb 18, 2021 at 15:25
  • 1
    FYI, [ is not part of if syntax. It's just one of the infinite number of commands you can use anywhere, including in an if, but you can use if without it; for example, if grep -qe pattern file; then... Commented Feb 18, 2021 at 15:29
  • Also, the only standard comparison operator inside [ is =, not ==. In some shells, using == will cause an error. Commented Feb 18, 2021 at 15:30
  • Anyhow -- the two duplicates this is closed with explain why using & causes the assignment to be ineffective. Commented Feb 18, 2021 at 15:34
  • 1
    @AndrewNewby, you can use triple-backticks to make single-backticks work in SO, though it's always better to use the POSIX-specified $(...) syntax instead; the standard-compliant syntax is easier to nest, doesn't make surprising changes to how backslashes behave within them, etc. -- and the POSIX sh standard has been out since 1992, so you don't need to worry about finding modern shells that don't support it. Commented Feb 18, 2021 at 21:16

1 Answer 1

3

There are a couple of errors.

  1. you echo do_exit before you set it to 1
  2. you have fi & sleep 5; which makes the if statement a child process, thus you can't use the value in the parent process
  3. -gt is for numeric comparisment, not strings.

Below should work for you.

#!/bin/bash

do_exit=0

while [ "$do_exit" == 0 ] ; do

    free=`free -m | grep Mem | awk '{print $4}'`

    if [[ $free -gt 0 ]]; then
        do_exit=1
        echo ${$do_exit}
    fi
    sleep 5;

done

You can break while loops as well. Check this:

#!/bin/bash

while true; do

    free=$(free -m | grep Mem | awk '{print $4}')

    if [[ $free -gt 0 ]]; then
        break;
    fi
    sleep 5;
done
1
  • Ahhh man that was it! So the problem turned out to be I was doing: fi & sleep 5; instead of fi, and then sleep 5 on another line! (that was some code I found online that seemed to work - I didn't realise it would cause complications later! Thanks for the explanation Commented Feb 18, 2021 at 15:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.