linuxbashyad

YAD multi-progress bar with background processes (bash)


I am trying to pipe multiple scripts into a YAD multi-progress bar and still obtain the exit status of the child processes. Here is what I have so far..

This would be my main script:

(./Script1.sh & X=$!) & (./Script2.sh & Y=$!) | yad --multi-progress \
    --bar "Bar1:"NORM --bar "Bar2:"NORM

wait $X
echo "Script 1 returned $?"
wait $Y
echo "Script 2 returned $?"

The two other scripts would just echo their progress and exit with a status (1 if failed). The problem is the exit status always returns 0. Any help in the right direction is appreciated:)


Solution

  • There are a few different problems in you script:

    1. () open a subshell, so your $Y and $X variables are defined in a subshell and can't be seen by the parent shell.
    2. After using & to send Script1 to the background, its output isn't caught by the pipe to YAD.
    3. Calling wait is useless in your case because by backgrounding Script2 inside a subshell and not backgrounding the subshell itself, the subshell will wait for all backgrounded processes to complete before exiting, so when you get to wait everything is already done.

    What can you do: I'm assuming Script1 and Script2 know to output their progress bar numbers (otherwise there'd be a bit of sed involved) so you just want to interleave their output in the pipe to YAD - so you want to run them under the same subshell and background both:

    (./Script1 & ./Script2 & wait ) | yad ...
    

    So that would get you some nice progress bars, but you also want to capture the scripts exit codes and transport them out of the shell. For that, you need another mechanism: you can't use shell variables - because these don't propagate out of the subshell, and you can't use exit code because the subshell only has one exit code (which is also being eaten by the pipe, but that can be worked around if there wasn't the first problem). Your best bet is a temp file, so sth like this:

    file=$(mktemp)
    (
        ./Script1 & e1=$!
        ./Script2 & e2=$!
        wait $e1; echo $? >> $file
        wait $e2; echo $? >> $file
    ) | yad ...
    e1=$(head -n1 $file | tail -n1)
    e2=$(head -n2 $file | tail -n1)
    rm -f $file