`[...] & wait $!` 的意义

`[...] & wait $!` 的意义

bash 模式的意义是什么[...] & wait $!?例如:

curl -LsS $AZP_AGENT_PACKAGE_LATEST_URL | tar -xz & wait $!

我将其理解为:

  1. 指示&bash 在后台子 shell 中运行先前的管道。
  2. 然后等待wait $!管道完成后再返回。

但如果是这样的话,它与仅仅运行管道本身有什么不同呢?重点是什么?

包含此示例(以及其他一些实例)的脚本可以在以下位置找到:

https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/docker?view=azure-devops

答案1

在非交互式 shell 中异步运行命令有两个不同A的副作用A & wait "$!"

  • 对于 .SIGINT 和 SIGQUIT 会被忽略A。如果您在运行时按Ctrl+ ,您会注意到已终止,但不是。Cbash -c 'sleep 1000 & wait "$!"'bashsleep

  • A的标准输入被重定向到/dev/null

    $ bash -c 'readlink /dev/fd/0'
    /dev/pts/4
    $ bash -c 'readlink /dev/fd/0 & wait "$!"'
    /dev/null
    

另一个区别是,在A | B & wait "$!"(其中$!包含最终运行的进程的 pid B) 中, 的退出状态A丢失($PIPESTATUS将仅包含一个条目, 的退出状态,如果未设置该选项wait,则为 的退出状态)。Bpipefail

In zsh、 in A | Bzsh等待AB,但 inA | B & wait $!只等待B(即使使用 , 的退出状态A也会丢失pipefail)。

另一个区别是,如果信号传递到 shell,它将立即处理并wait返回(即使它正在等待的进程尚未完成)。

比较:

$ bash -c 'trap "echo Ouch" TERM; sleep 10 & wait "$!"; echo "$?"' & sleep 1; kill "$!"
[1] 13749
Ouch
143

Ouch一旦SIGTERM发送到bash(并在终止sleep 10后继续运行)输出bash

$ 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 "$?"'

Ouchreturn后才在哪里输出sleep 10

脚本作者是否想要这些副作用是另一回事。您会注意到该脚本中的许多其他错误,很可能编写该脚本的人不太了解 shell 脚本。

相关内容