Running multiple concurrent processes in a bash script, such that if one dies it takes the other ones down with it

huangapple go评论57阅读模式
英文:

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"
英文:

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 &amp; sleep 31 &amp; sleep 32 &amp; sleep 33 &amp; sleep 34 &amp; sleep 35 &amp; sleep 36 &amp;
sleep 5 &amp;

# 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 &#39;Killing: %s\n&#39; &quot;$cmd&quot; &gt;&amp;2
    kill &quot;%${num//[^[:digit:]]/}&quot;
done &lt;&lt;&lt;&quot;$jobs&quot;
  • The -n option for wait 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.

  1. Whenever a job dies, it kills the parent script.
  2. 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.

  1. Whenever a job dies, it kills the parent script
  2. 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 &quot;Process $1 is working...&quot;
    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&gt; /dev/null
}

(
    trap terminate_parent_process EXIT
    process 1
) &amp;

(
    trap terminate_parent_process EXIT
    process 2
) &amp;

wait

huangapple
  • 本文由 发表于 2023年3月21日 02:55:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75794235-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定