use*_*972 2 bash shell-script posix wait
我正在编写一个脚本,它在后台同时执行一堆命令,然后等待它们全部完成:
#!/bin/sh -fx
./p1 &
./p2 &
./p3 &
./p4 &
./p5 &
wait
Run Code Online (Sandbox Code Playgroud)
问题是,如果这些过程中的一个或多个失败,它就会继续下去。如何同时执行所有这些命令并检查一个或多个命令是否失败?
您可以等待各个 pid 获取其退出状态:
\n#! /bin/sh -\nset -o xtrace -o noglob\n\n./p1 & p1=$!\n./p2 & p2=$!\n./p3 & p3=$!\n./p4 & p4=$!\n./p5 & p5=$!\nfail=0\nfor pid in "$p1" "$p2" "$p3" "$p4" "$p5"; do\n wait "$pid" || fail=$(( fail + 1 ))\ndone\necho>&2 "$fail failed"\nexit "$(( fail > 0 ))"\n
Run Code Online (Sandbox Code Playgroud)\n请注意,我们不一定按照这些进程终止的顺序等待它们,但wait pid
仍然应该努力检索 pid 的退出状态,即使wait
在 pid 已经退出后调用 。
另一种方法是使用大多数实现\xc2\xb9pipefail
支持的选项,并将出现在 POSIX 标准的下一版本中:sh
#! /bin/sh -\nset -o xtrace -o noglob -o pipefail\nalias r=\'<&3 3<&- >&4 4>&-\'\n\ndie() { printf>&2 \'%s\\n\' "$@"; exit 1; }\n\n{\n r ./p1 | r ./p2 | r ./p3 | r ./p4 | r ./p5\n} 3<&0 4>&1 || die "At least one of them failed"\n
Run Code Online (Sandbox Code Playgroud)\n我们在管道中启动它们,但不使用管道。我们借助该r
别名将这些进程的 stdin 和 stdout 恢复为保存在 fd 3 和 4 上的原始值。
\xc2\xb9 不幸的是dash
还没有,尽管大多数其他基于 ash 的 shell 已经支持它。