1

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:)

Guss
  • 30,470
  • 17
  • 104
  • 128
Jon Bell
  • 17
  • 5

1 Answers1

1

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
Guss
  • 30,470
  • 17
  • 104
  • 128
  • Regarding (3), this would normally work - you can background a process in a subshell and then exit the subshell, leaving the internal process backgrounded, but because you pipe the subshell to something, the pipe holds the subshell's `stdout` and the consuming program waits until the subshell's stdout ends - which is only when all internal backgrounded processes close their outputs. – Guss Apr 13 '18 at 13:18
  • Awesome answer Guss. Thanks for the help. One more question, do you know why the cancel button on the yard progress bar doesn't return an exit code of 1? It's 0 no matter what.. – Jon Bell Apr 13 '18 at 14:02
  • There's no "cancel" button on the yad progress dialogs. There's "Close" which just closes the dialog. If you want to detect cancel, consider using Zenity instead (even though it doesn't have multi-progress). – Guss Apr 13 '18 at 14:56
  • Gotcha. I actually just added a cancel button with --button="Cancel":1 which will make it return 1. Thanks again for the help! – Jon Bell Apr 13 '18 at 15:24