I wrote a script that contains an until loop. This loop should run till a boolean variable is set to true from outside the loop. Unfortunately the loop ignores that the variable has been set to true and keeps running. Here are a few lines which generate this problem:

{ sleep 5 && boolean=true && echo "boolean is true now" ; } &
{ until [ "$boolean" = true ] ; do sleep 1 && echo $boolean ; done ; } &&
echo "boolean is true now: $boolean"

The output this generates is:

boolean is true now

How can I make the loop exit when the boolean is set to true?


The & character makes a background process. A background process is executed asynchronously in a subshell. Variables can be passed from a parent shell to sub shell, not the other way around. However, you can do a workaround if you are really in need of the value set in the child shell:

boolean=$(mktemp) && echo "false" >$boolean
{ sleep 5 && echo true >$boolean && echo "boolean is true now" ; } &
{ until [ "$(cat $boolean)" = "true" ] ; do sleep 1 && cat $boolean ; done ; } &&
echo "boolean is true now: $(cat $boolean)"

That makes a temporary file whose content is the boolean value. In the until loop that file is checked until it contains true.


I recommend to do the following in your script (if possible):

{ sleep 5 && echo "background process done" ; } &
echo "continue in foregound."

wait waits for the background process to finish.

| improve this answer | |
  • Thanks. This works fine. I would use wait but the background process in my script is always running. – tigger92 Aug 25 '15 at 13:00
  • What's the point of running something asynchronously, then waiting for it to finish? Just run it normally. – user253751 Aug 26 '15 at 3:51
  • @immibis I think that between the job and the wait the asker has some code. – chaos Aug 26 '15 at 5:26

It's possible to use signals to communicate between the foreground and background shells:


# global variable for foreground shell

# register a signal handler for SIGUSR1
trap handler USR1

# the handler sets the global variable
handler() { boolean=true; }

echo "before: $boolean"

# Here, "$$" is the pid of the foreground shell
{ sleep 5; kill -USR1 $$; echo "finished background process"; } &

# busy waiting
until $boolean; do 
    echo "waiting..."
    sleep 1

echo "after: $boolean"


before: false
finished background process
after: true
| improve this answer | |
  • 1
    +1 Signals are the right way to pass asynchronous notifications between processes. – alexis Aug 26 '15 at 9:22
  • Using USR1, how to pass value instead of asynchronous notifications between processes? – Unknown123 Jul 1 at 1:29

You mistakenly assume that the boolean you set to true in the second line is the same boolean that you test for in the until statement. That is not the case, you start new process, with a new shell in the background and boolean (the one you test for), never gets assigned.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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