使 bash wait 命令在第一个错误时失败

Çağ*_*ürk 1 bash

我有一个 bash 脚本,可以并行执行一些耗时的命令,到目前为止它运行得很好。我正在使用等待命令,如下所示:

docker pull */* &
docker pull */* &
docker pull */* &
docker pull */* &
docker pull */* &
docker pull */* &
docker pull */* &
composer install -n &
wait
Run Code Online (Sandbox Code Playgroud)

现在,我希望此脚本中止所有命令,并在其中一个命令失败时给出退出代码。如何实现这一目标?

注:*/*是docker镜像名称,对于上下文来说不重要

Win*_*ute 5

这将需要 bash wait -n

这里的技巧是保留您生成的子进程的列表,然后单独等待它们(按照它们完成的顺序)。然后,您可以检查已完成进程的返回代码,如果失败则杀死其中的很多进程。例如:

#!/bin/bash

# Remember the pid after each command, keep a list of them.
# pidlist=foo could also go on a line of its own, but I
# find this more readable because I like tabular layouts.
sleep 10 & pidlist="$!"
sleep 10 & pidlist="$pidlist $!"
sleep 10 & pidlist="$pidlist $!"
sleep 10 & pidlist="$pidlist $!"
sleep 10 & pidlist="$pidlist $!"
sleep 10 & pidlist="$pidlist $!"
false    & pidlist="$pidlist $!"

echo $pidlist

# $pidlist intentionally unquoted so every pid in it expands to a
# parameter of its own. Note that $i doesn't have to be the PID of
# the process that finished, it's just important that the loop runs
# as many times as there are PIDs.
for i in $pidlist; do
    # Wait for a single process in the pid list to finish,
    # check if it failed,
    if ! wait -n $pidlist; then
        # If it did, kill the lot. pipe kill's stderr
        # to /dev/null so it doesn't complain about
        # already-finished processes not existing
        # anymore.
        kill $pidlist 2>/dev/null

        # then exit with a non-zero status.
        exit 1
    fi
done
Run Code Online (Sandbox Code Playgroud)

  • 为什么这样一个基本的命令在其工作中表现得如此糟糕?我正在尝试制作一个简单的构建脚本,步骤 A、B,然后是 C——这些应该同时运行,并且整个事情应该在第一次失败时崩溃。相反,现在我有一个永远不会失败的 npm 构建例程,现在我必须用 Gulp 或其他东西重写它,因为如果我想制作一个外部 build.sh 脚本,上面的示例就可以工作,但这绝对是一个悲惨的解决方案。我期待类似“wait --all”(我将当前行为称为“wait --any”)之类的内容...我不敢相信这里的复杂性。 (3认同)
  • 两个注意事项:`wait -n` 需要 `bash` 4.3 或更高版本,并且您可以使用 `jobs -p` 而不是手动维护 `pidlist`。 (2认同)