Search code examples
loopsshposixinfinite-loop

How can I set a variable to the output of an infinite loop in Posix shell script?


You can set a variable to a subshell's output like so in Bash, sh, etc.

$ var=$(echo "2")

$ echo $var
2

You can also set a variable to the output of a loop once it's completed.

$ i=0
$ var=$(while [ $i -ne 4 ]; do echo "$i"; i=$((i+1)); done)
$ echo "$var"
0
1
2
3

Is there anyway I can fork this loop, keep it running forever, and just get the latest version of the variable whenever it's referenced? I tried the following code but it gave no output.

$ i=0
$ var=$(while true; do echo "$i"; i=$((i+1)); sleep 1; done) &
$ sleep 2
$ echo "$var"

I thought the variable was never set because the loop never finished. I would like for the output to be "3" here, and if I echo "$var" two seconds later, the output "5". As @user2864740 stated, the issue is related to the process being forked in the background. Is there a solution here, if I want the rest of my code to run while the infinite loop is running?


Solution

  • I would like for the output to be "3" here, and if I echo "$var" two seconds later, the output "5".

    You cannot automatically assign a variable from inside a (sub)process. But you can access the most recent value from the loop using a temporary file that you overwrite with each iteration.

    Of course you can save the value in a variable (var=$(< file)) or access the file directly (cat file).

    trap 'kill $(jobs -p); rm -f loopoutput' EXIT
    
    i=0
    while true; do echo "$i" > loopoutput; i=$((i+1)); sleep 1; done &
    sleep 4
    cat loopoutput
    sleep 2
    cat loopoutput
    

    prints

    3
    5
    

    The trap is only there to end the loop after the script finished and to delete the temporary file.