如何在 bash 脚本中等待子进程,如果其中一个失败所以停止所有人
How to wait in bash script to subprocess, if one of them failed so stop everyone
如何在 bash 脚本中等待子进程,如果其中之一 return 退出代码 1 所以我想停止所有子进程。
这就是我尝试做的。
但是有一些问题:
如果第一个进程比所有其他进程都长,并且另一个进程在后台失败...那么脚本会等待第一个进程完成,即使另一个进程已经失败。
无法检测到 doSomething 失败,因为我使用管道作为所需的打印格式。
#!/bin/bash
function doSomething()
{
echo [ start ]
sleep
if [ == 10 ]; then
failed
fi
echo [ sleep ]: done
}
function failed(){
sleep 2
echo ------ process failed ------
exit 1
}
function process_log() {
local NAME=
while read Line; do
echo [Name ${NAME}]: ${Line}
done
}
pids=""
(doSomething 4 | process_log 4)&
pids+="$! "
(doSomething 17 | process_log 17)&
pids+="$! "
(doSomething 6 | process_log 6)&
pids+="$! "
(doSomething 10 | process_log 10)&
pids+="$! "
(doSomething 22 | process_log 22)&
pids+="$! "
(doSomething 5 | process_log 5)&
pids+="$! "
for pid in $pids; do
wait $pid || (pkill -P $$ ; break)
done
echo done program
有人有想法吗?
它的要点是:
#!/bin/bash
set -m # needed for using negative PIDs
trap '{ kill -- $(jobs -rp | sed s/^/-/); wait; } 2> /dev/null' USR1
doSomething() {
echo "[ start ]"
sleep ""
[[ == 10 ]] && failed
echo "[ sleep ]: done"
}
failed(){
echo "------ process failed ------" 1>&2
kill -USR1 "$$"
}
process_log() {
local name="" line
while IFS='' read -r line; do
echo "[Name $name]: $line"
done
}
{ doSomething 4 | process_log 4; } &
{ doSomething 17 | process_log 17; } &
{ doSomething 6 | process_log 6; } &
{ doSomething 10 | process_log 10; } &
{ doSomething 22 | process_log 22; } &
{ doSomething 5 | process_log 5; } &
wait
echo "done program"
[Name 4]: [ 4 start ]
[Name 6]: [ 6 start ]
[Name 17]: [ 17 start ]
[Name 5]: [ 5 start ]
[Name 10]: [ 10 start ]
[Name 22]: [ 22 start ]
[Name 4]: [ sleep 4 ]: done
[Name 5]: [ sleep 5 ]: done
[Name 6]: [ sleep 6 ]: done
------ process failed ------
[Name 10]: [ sleep 10 ]: done
done program
解释
想法是让 sub-processes 在失败时通知父脚本(使用 SIGUSR1
信号);主脚本将在收到该信号时杀死所有 sub-processes。
但是有一个问题:杀死 sub-process 的 PID 可能还不够,例如当它当前是 运行 一个带有 |
的命令时。在这些情况下,您需要终止整个 进程组 ,这可以通过使用 set -m
启用 job control 并使用kill
命令中的负 PID。
如何在 bash 脚本中等待子进程,如果其中之一 return 退出代码 1 所以我想停止所有子进程。
这就是我尝试做的。 但是有一些问题:
如果第一个进程比所有其他进程都长,并且另一个进程在后台失败...那么脚本会等待第一个进程完成,即使另一个进程已经失败。
无法检测到 doSomething 失败,因为我使用管道作为所需的打印格式。
#!/bin/bash
function doSomething()
{
echo [ start ]
sleep
if [ == 10 ]; then
failed
fi
echo [ sleep ]: done
}
function failed(){
sleep 2
echo ------ process failed ------
exit 1
}
function process_log() {
local NAME=
while read Line; do
echo [Name ${NAME}]: ${Line}
done
}
pids=""
(doSomething 4 | process_log 4)&
pids+="$! "
(doSomething 17 | process_log 17)&
pids+="$! "
(doSomething 6 | process_log 6)&
pids+="$! "
(doSomething 10 | process_log 10)&
pids+="$! "
(doSomething 22 | process_log 22)&
pids+="$! "
(doSomething 5 | process_log 5)&
pids+="$! "
for pid in $pids; do
wait $pid || (pkill -P $$ ; break)
done
echo done program
有人有想法吗?
它的要点是:
#!/bin/bash
set -m # needed for using negative PIDs
trap '{ kill -- $(jobs -rp | sed s/^/-/); wait; } 2> /dev/null' USR1
doSomething() {
echo "[ start ]"
sleep ""
[[ == 10 ]] && failed
echo "[ sleep ]: done"
}
failed(){
echo "------ process failed ------" 1>&2
kill -USR1 "$$"
}
process_log() {
local name="" line
while IFS='' read -r line; do
echo "[Name $name]: $line"
done
}
{ doSomething 4 | process_log 4; } &
{ doSomething 17 | process_log 17; } &
{ doSomething 6 | process_log 6; } &
{ doSomething 10 | process_log 10; } &
{ doSomething 22 | process_log 22; } &
{ doSomething 5 | process_log 5; } &
wait
echo "done program"
[Name 4]: [ 4 start ]
[Name 6]: [ 6 start ]
[Name 17]: [ 17 start ]
[Name 5]: [ 5 start ]
[Name 10]: [ 10 start ]
[Name 22]: [ 22 start ]
[Name 4]: [ sleep 4 ]: done
[Name 5]: [ sleep 5 ]: done
[Name 6]: [ sleep 6 ]: done
------ process failed ------
[Name 10]: [ sleep 10 ]: done
done program
解释
想法是让 sub-processes 在失败时通知父脚本(使用 SIGUSR1
信号);主脚本将在收到该信号时杀死所有 sub-processes。
但是有一个问题:杀死 sub-process 的 PID 可能还不够,例如当它当前是 运行 一个带有 |
的命令时。在这些情况下,您需要终止整个 进程组 ,这可以通过使用 set -m
启用 job control 并使用kill
命令中的负 PID。