如何在退出时杀死bash脚本的所有子进程?

时间:2016-10-24 20:06:47

标签: bash shell bash-trap

我使用命名管道在3种过程之间进行通信:生产者,一些读者和一些作家。然后我创建了一个脚本,只是它运行所有进程,我希望当run.sh进程被终止或它终止所有子进程也被杀死。 run.sh脚本如下:

#!/bin/bash
MAX_WRITERS=2
MAX_READERS=2

trap 'jobs -p | xargs kill' EXIT

./producer.sh &
for ((i=1; i<=$MAX_READERS; i++)); do ./reader_one.sh & done
for ((i=1; i<=$MAX_WRITERS; i++)); do ./writer_one.sh & done
wait

脚本非常简单,但似乎不起作用,因为我仍然可以看到一些进程正在运行(只有producer.sh已被杀死)。

$ ./run.sh
... some activities ...
^C
$ ps aux | grep "[b]ash ./"
user         48909   ... /bin/bash ./writer_one.sh
user         48906   ... /bin/bash ./writer_one.sh
user         48904   ... /bin/bash ./reader_one.sh
user         48901   ... /bin/bash ./reader_one.sh

所以我必须杀了这个:

$ ps aux | grep "[b]ash ./" | awk '{print $2}' | xargs kill

我怎样才能使它有效?

更新1: 似乎已在&后台运行的作业可以抵抗信号SIGINT,因此简单kill无用。在陷阱中使用kill -9kill -TERM,他们将收到信号,但它们仍然存在,只有producer.sh被正确杀死。

./run.sh: line 21: 50039 Killed: 9               ./producer.sh
./run.sh: line 21: 50040 Killed: 9               ./reader_one.sh
./run.sh: line 21: 50041 Killed: 9               ./reader_one.sh
./run.sh: line 21: 50042 Killed: 9               ./writer_one.sh
./run.sh: line 21: 50043 Killed: 9               ./writer_one.sh

$ ps aux | grep "[b]ash ./"
user         50069   ... /bin/bash ./writer_one.sh
user         50068   ... /bin/bash ./writer_one.sh
user         50064   ... /bin/bash ./reader_one.sh
user         50061   ... /bin/bash ./reader_one.sh

更新2: reader_one.shwriter_one.sh正在等待命名管道中的数据。

更新3: 这里是read_one.sh的代码;可能原因是子壳,因为管道就在while

之前
init_read(){
...
}

read_one(){
...
}

init_reader
while true; do
  cat to_read | while read line; do
    read_one $line;
  done
done

1 个答案:

答案 0 :(得分:1)

@Barmar的建议以正确的方式告诉我。问题与管道创建的子shell有关,所以我在writer_one.shreader_one.sh

中更改了此问题
cat to_read | while read line; do
    read_one $line;
done

到此:

while read line; do
    read_one $line;
done < to_read