英文:
Running multiple concurrent processes in a bash script, such that if one dies it takes the other ones down with it
问题
我想同时运行一系列命令,以便如果其中一个终止,它们全部停止。
英文:
I want to run a series of commands concurrently such that if one of them dies they all stop.
答案1
得分: 1
如果您使用Bash 4.3(2014年)或更新版本,这段Shellcheck清理过的代码演示了一种执行的方法:
#! /bin/bash -p
# 启动一些并发进程
sleep 30 & sleep 31 & sleep 32 & sleep 33 & sleep 34 & sleep 35 & sleep 36 &
sleep 5 &
# 等待任何作业完成
wait -n
# 获取仍在运行的作业列表,然后杀死它们
jobs=$(jobs -r)
while read -r num _ cmd; do
printf 'Killing: %s\n' "$cmd" >&2
kill "%${num//[^[:digit:]]/}"
done <<< "$jobs"
-n
选项是Bash 4.3引入的wait
选项,因此该代码不适用于较旧版本的Bash。- 参见ProcessManagement - Greg's Wiki以了解有关在Bash中处理并发进程的技巧。它解释了代码中使用的所有进程控制和监视机制。
num
变量的一个示例值是[3]+
。${num//[^[:digit:]]/}
通过删除所有非数字字符来提取作业编号(在本例中为3
)。有关${var//old/}
的更多信息,请参阅Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?))。
英文:
If you've got Bash 4.3 (2014) or later, this Shellcheck-clean code demonstrates one way to do it:
#! /bin/bash -p
# Start some concurrent processes
sleep 30 & sleep 31 & sleep 32 & sleep 33 & sleep 34 & sleep 35 & sleep 36 &
sleep 5 &
# Wait for any job to complete
wait -n
# Get the list of still running jobs, and kill them
jobs=$(jobs -r)
while read -r num _ cmd; do
printf 'Killing: %s\n' "$cmd" >&2
kill "%${num//[^[:digit:]]/}"
done <<<"$jobs"
- The
-n
option forwait
was introduced in Bash 4.3, so the code will not work with older versions of Bash. - See ProcessManagement - Greg's Wiki to learn about techniques for working with concurrent processes in Bash. It explains all of the process control and monitoring mechanisms used in the code.
- An example value of the
num
variable is[3]+
.${num//[^[:digit:]]/}
extracts the job number (3
in this case) by removing all non-digit characters. See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)) for more information about${var//old/}
.
答案2
得分: 0
This is my solution using job control.
- Whenever a job dies, it kills the parent script.
- When the parent script dies, it kills the whole process group, including all jobs.
I would hope that there's something simpler out there.
#!/usr/bin/env bash
# Mocks
function process () {
while true ; do
echo "Process $1 is working..."
sleep 10
done
}
# Actual implementation
trap terminate_entire_process_group EXIT
function terminate_entire_process_group () {
trap - EXIT
kill -15 -$$
}
function terminate_parent_process () {
trap - EXIT
kill $$ 2> /dev/null
}
(
trap terminate_parent_process EXIT
process 1
) &
(
trap terminate_parent_process EXIT
process 2
) &
wait
Note: I've retained the code part as requested and translated the surrounding text.
英文:
This is my solution using job control.
- Whenever a job dies, it kills the parent script
- When the parent script dies, it kill the whole process group, including all jobs
I would hope that there's something simpler out there.
#!/usr/bin/env bash
# Mocks
function process () {
while true ; do
echo "Process $1 is working..."
sleep 10
done
}
# Actual implementation
trap terminate_entire_process_group EXIT
function terminate_entire_process_group () {
trap - EXIT
kill -15 -$$
}
function terminate_parent_process () {
trap - EXIT
kill $$ 2> /dev/null
}
(
trap terminate_parent_process EXIT
process 1
) &
(
trap terminate_parent_process EXIT
process 2
) &
wait
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论