在cloudfoundry /dea中启动一个实例时,会用一个脚本启动多个后台子进程.当发现进程消失时,会在清理该实例后,重新启动一个实例.
启动脚本一般是这个样子
1 2 |
a.sh & wait |
这没有什么问题,当需要多个子进程,那么看上去应该是这个样子
1 2 3 |
a.sh & b.sh & wait |
问题出现了
1 我们可能希望的效果是当任意子进程结束,结束所有子进程后,脚本退出
2 wait 会等待a.sh和b.sh都退出后,才释放,这不是我们希望的
能监听单个子进程的waitpid在shell脚本里不提供,这里可以用信号来处理
子进程退出时,会给父进程发送一个CHLD信号
但在dash环境中,只有后台子进程退出时,才会给父进程发送CHLD信号,所以选择dash执行脚本
那么脚本看上去就是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/bin/dash kill_tree() { if [ $# -eq 0 ]; then return 0 fi for pid in $*; do kill_tree `pgrep -P $pid -d ' '` done kill -9 $* } clean_jobs() { trap CHLD kill_tree `pgrep -P $$ -d ' '` } trap "clean_jobs" CHLD a.sh & b.sh & wait |
这样,当a.sh或者b.sh任何一个退出了,就会执行clean_jobs函数,然后调用kill_tree杀掉当前进程的所有子进程后退出,说明如下:
1 2 |
#当收到CHLD信号时,执行clean_jobs trap "clean_jobs" CHLD |
1 2 |
#为了避免反复调用clean_jobs,在第一次调用clean_jobs函数时,恢复CHLD信号的默认操作 trap CHLD |
1 2 |
#常用的信号还有INT,TERM,可以用kill命令查看 kill -l |
*以上脚本在centos6.3,ubuntu12.04上工作正常
3 Comments
波哥,是bash吧。擦,居然没表情插件……
bash和dash对chld信号的处理方式不一样,我这里用的是dash
dash是FreeBSD上的ash,移植到debian上的版本