2

I am trying to write a bash script that echoes values of 2 variables in parallel as part of an experiment before writing a shell script that generates files with numbers appended to them in parallel for a project of mine.

Here is the shell script:

#!/bin/bash

value1=0
value2=1
for i in $(seq 1 2); do
    echo "Value 1 : " $((++value1)) &
    echo "Value 2 : " $((++value2))
    wait
    echo "Wait"
    done

And here is the output I get:

Value 2 :  2
Value 1 :  1
Wait
Value 2 :  3
Value 1 :  1
Wait

I know about GNU parallel and xargs but I don't want to use them.

I would like to know why 'value2' gets printed first and why 'value1' never gets incremented.

7
  • What happens when you remove the & ? Commented Jan 6, 2017 at 3:07
  • @KraangPrime then the output is as expected. But I want to do this in parallel hence the '&' Commented Jan 6, 2017 at 3:09
  • 1
    value1 never gets incremented because the background process runs in a sub shell, where any changes made to values don't get reported back to the parent shell. And value2 probably gets printed first because the shell handles the next line of execution before the subshell has managed to get its thoughts in order and produce output, but that order is not guaranteed. The two processes are running in parallel, and either could win the race to echo. Commented Jan 6, 2017 at 3:11
  • 2
    You backgrounded the line that handles value1. The main thread of execution remains while the backgrounded process is forked off as a separate shell. Imagine if the value1++ took a while to process. At what point in the execution of the main script would you expect that variable to change, and what would actually cause it to change? What if other lines of the script were using and changing that variable? Commented Jan 6, 2017 at 3:19
  • 2
    And .. yes, there's always a way that you can do things, though the method may be painful, especially in a shell script. If you want to be able to fire off a background process and have it return something to the main script, you could have the script record its output to a temporary file, then have the backgrounded process send a signal (with kill) to the main process which would execute a trap. Or you could send results back through a named pipe. Of course, there may be another way to parallelize whatever it is you're trying to do; I don't have enough info to make a recommendation. Commented Jan 6, 2017 at 3:22

1 Answer 1

4

value1 is incremented, but in a separate process. value1 in the original process is not modified. There is no guarantee which value you will see printed first; the two echo statements occur in two different processes which are scheduled at the whim of the operating system.

Sign up to request clarification or add additional context in comments.

3 Comments

Isn't it command line parsing done before the child process is started? I would have expected that the main process first resolves parameter substitution (which would turn the line into echo Value 1 : 1, and then have this command be run in a child process. Hence, the change in value should be visible in the process, and the child process doesn't even see a shell variable of this name.
Parsed, yes; evaluated, no. The shell forks as soon as possible.
Again something learned. Makes sense after all. If it were otherwise, a command like a $(b) & would execute b in the foreground.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.