bash脚本退出时如何杀死所有子进程?
How to kill all the sub processes of bash script when it exits?
我正在使用命名管道在 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 }' | xargs kill
我怎样才能让它发挥作用?
更新 1:
似乎已经在后台运行 &
的作业可以抵抗信号 SIGINT
,所以简单的 kill
是没有用的。在陷阱中使用 kill -9
或 kill -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
更新二:
reader_one.sh
和 writer_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
@Barmar 的建议让我找到了正确的方法。问题与管道 while 创建的子外壳有关,所以我在 writer_one.sh
和 reader_one.sh
中更改了它
cat to_read | while read line; do
read_one $line;
done
对此:
while read line; do
read_one $line;
done < to_read
我正在使用命名管道在 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 }' | xargs kill
我怎样才能让它发挥作用?
更新 1:
似乎已经在后台运行 &
的作业可以抵抗信号 SIGINT
,所以简单的 kill
是没有用的。在陷阱中使用 kill -9
或 kill -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
更新二:
reader_one.sh
和 writer_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
@Barmar 的建议让我找到了正确的方法。问题与管道 while 创建的子外壳有关,所以我在 writer_one.sh
和 reader_one.sh
cat to_read | while read line; do
read_one $line;
done
对此:
while read line; do
read_one $line;
done < to_read