2

In a bash script a function is called in the background several times,each of which have different execution time.
The functions are supposed to print the value of a global variable, which is changed before each call of the function.
What I notice is that the value of the variable is "locked" to the one when the function was called and not the updated one.
Is there a way to get the updated value?

The following code as a script file demonstrates the situation.

#!/bin/bash

declare -i Tests_to_run=6
Simultaneous_tests=3
declare -i test_index=0

run_test(){
   Time_to_sleep=$((1+${RANDOM} % 5))
   echo "Running test $1/${Tests_to_run}, sleeping for ${Time_to_sleep}"
   sleep ${Time_to_sleep}
   echo "Run $1 Finished!!! You have submitted ${test_index} tests..."
   unset Time_to_sleep
}

run_tests(){
   for test in $(seq 1 ${Tests_to_run}) ; do
      while [ $(pgrep -c sleep) -ge ${Simultaneous_tests} ] ; do sleep 5 ; done
      test_index=$((${test_index} + 1))
      run_test ${test_index} &
   done
}

run_tests

while [ $(pgrep -c sleep) -ge 1 ] ; do sleep 5 ; done

exit 0

If I run this script I get as an output the following

Running test 1/6, sleeping for 5
Running test 2/6, sleeping for 5
Running test 3/6, sleeping for 4
Run 3 Finished!!! You have submitted 3 tests...
Run 1 Finished!!! You have submitted 1 tests...
Run 2 Finished!!! You have submitted 2 tests...
Running test 4/6, sleeping for 1
Running test 5/6, sleeping for 3
Running test 6/6, sleeping for 5
Run 4 Finished!!! You have submitted 4 tests...
Run 5 Finished!!! You have submitted 5 tests...
Run 6 Finished!!! You have submitted 6 tests...

I would expect that in the first bunch of "Run # Finished..." all the submitted tests should be 3 and in the second bunch all of them 6.
Instead the number of submitted tests is the same as the test number, though in the meantime it is changed!

psaxioti
  • 23
  • 4
  • 1
    `run_test ${test_index} &` -- the `&` forks off a copy of the process. That copy's variables are independent. – Charles Duffy Dec 15 '21 at 19:05
  • That said, the functions are looking at `$1`, not at `$test_index` or `$test`; I'm unclear why you would ever expect them all to have the same shared value: When you pass `$test_index` as a parameter (to become `$1` inside the called context), the _value_ is passed to the command being run, not a reference to the variable from which that value was originally populated. So it would still behave this same way even if there _were_ a shared namespace for globals that spanned subshells. – Charles Duffy Dec 15 '21 at 19:08
  • To be fair Charles, the function uses `$1` and `$test_index` separately. – glenn jackman Dec 15 '21 at 19:10
  • Ah -- yeah, if it's `test_index` that the OP meant should be printing the shared value, that makes more sense. – Charles Duffy Dec 15 '21 at 19:11

1 Answers1

2

I think it's because you're running in the background.

The function execution will be put into a subshell, and the subshell contains a copy of the parent shell's environment. This snapshot is taken at the instant the function invocation is backgrounded. Altering the parent shell's variable will not affect the copy in the child shell.

You may be forced to use files to share data between the various shell processes.

References:

glenn jackman
  • 238,783
  • 38
  • 220
  • 352