How to wait for background commands that were executed within a subshell?
5
votes
2
answers
221
views
Given this code:
#!/bin/bash
set -euo pipefail
function someFn() {
local input_string="$1"
echo "$input_string start"
sleep 3
echo "$input_string end"
}
function blocking() {
someFn "FOO"
someFn "BAR"
someFn "BAZ"
echo "DONE"
}
function wellBehavedParallel() {
someFn "FOO" &
someFn "BAR" &
someFn "BAZ" &
wait
echo "DONE"
}
function subShellMadness() {
(someFn "FOO" &) &
(someFn "BAR" &) &
(someFn "BAZ" &) &
wait
echo "DONE"
}
echo "BLOCKING_APPROACH"
blocking
echo "WEL_WORKING_PARALLEL"
wellBehavedParallel
echo "THIS DOES NOT WORK"
subShellMadness
It showcases two expected behaviors and one unexpected.
1. The Blocking one
Simple, executes one line, then the next, slow and boring but solid:
BLOCKING_APPROACH
FOO start
FOO end
BAR start
BAR end
BAZ start
BAZ end
DONE
2. The well-behaved parallel one. All commands &
are executed in parallel, the wait
waits for all of them to finish, and only then does the main script progress further:
WEL_WORKING_PARALLEL
FOO start
BAR start
BAZ start
FOO end
BAR end
BAZ end
DONE
2. This is (at least to me) unexpected, but I assume this is "by design" that once I use subshells, I cannot use wait
in the main script any more.
The jobs are still progressed in parallel, but I have lost all control, the main script even ends, and afterwards output is still dumped on the terminal by the subshells:
THIS DOES NOT WORK
FOO start
BAR start
DONE
BAZ start
philipp@DESKTOP-H0QQ2H8:~$ FOO end
BAR end
BAZ end
Is there a way from a main script to wait for subshells to finish?
I want to avoid PID-collecting solutions (I know that wait
accepts PID as a parameter), yet from what I gather getting the right PID in the first place may be prone to race conditions (since $!
will represent the last executed command's PID, not necessarily my command), and I fear PID-reusage could also make such an approach prone to unexpected behavior (am I waiting on my original command, or did some other process take my pid? When calling wait
, I seemingly have no way of knowing).
Is there a best practice in dealing with waiting for subshells that reliably waits for them to finish?
(Not using subshells is not an option for me right now.)
Asked by k0pernikus
(16551 rep)
Aug 9, 2025, 01:10 PM
Last activity: Aug 10, 2025, 02:02 PM
Last activity: Aug 10, 2025, 02:02 PM