Significance of `[…] & wait $!`
What is the significance of the bash pattern [...] & wait $!
? For example:
curl -LsS $AZP_AGENT_PACKAGE_LATEST_URL | tar -xz & wait $!
I understand this as:
- The
&
instructs bash to run the prior pipeline in a background subshell. - The
wait $!
then waits for the pipeline to finish before returning.
But if that’s the case, how is it any different from just running the pipeline itself? What’s the point?
The script containing this example (and a few other instances) can be found at:
https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/docker?view=azure-devops
There are two side effects of running a command asynchronously in a non-interactive shell that make A
and A & wait "$!"
different:
-
SIGINT and SIGQUIT are ignored for
A
. If you press Ctrl+C, whilst runningbash -c 'sleep 1000 & wait "$!"'
, you’ll noticebash
is terminated, but notsleep
. -
A
‘s stdin is redirected to/dev/null
:$ bash -c 'readlink /dev/fd/0' /dev/pts/4 $ bash -c 'readlink /dev/fd/0 & wait "$!"' /dev/null
Another difference is that in A | B & wait "$!"
(where $!
contains the pid of the process eventually running B
), the exit status of A
is lost ($PIPESTATUS
will contain only one entry, the exit status of wait
, which will be that of B
if the pipefail
option is not set).
In zsh
, in A | B
, zsh
waits for both A
and B
, but in A | B & wait $!
only waits for B
(and the exit status of A
is lost even with pipefail
).
Another difference is that if a signal is delivered to the shell, it will be handled straight away and wait
will return (even if the process it’s waiting for is not finished).
Compare:
$ bash -c 'trap "echo Ouch" TERM; sleep 10 & wait "$!"; echo "$?"' & sleep 1; kill "$!"
[1] 13749
Ouch
143
Where Ouch
is output as soon as SIGTERM
is sent to bash
(and sleep 10
carries on running after bash
terminates) with:
$ bash -c 'trap "echo Ouch" TERM; sleep 10; echo "$?"' & sleep 1; kill "$!"
[1] 13822
$ Ouch 6:11
0
[1] + done bash -c 'trap "echo Ouch" TERM; sleep 10; echo "$?"'
Where Ouch
is output only after sleep 10
returns.
Whether any of those side effects were wanted by the script author is another matter. You’ll notice many other mistakes in that script, it’s very well possible that whoever wrote that script didn’t know much about shell scripting.