把下面脚本当做容器的init进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#!/bin/bash # kill all process except pid=1 export TZ=UTC-8 trap "quit; exit " 1 2 3 15 function log() { echo $(date +"%F %T") "$@" } function quit() { while :; do local pid_info=$(ps -axo pid,ppid,comm --no-headers|awk '$1 != 1 {print $0}') [[ $pid_info == "" ]] && break local succ=0 while read pid ppid comm; do if kill $pid &>/dev/null; then ((succ++)) log "$(printf '%-64s[%s]' "killing pid $pid(ppid: $ppid, comm: $comm)" succ)" else log "$(printf '%-64s[%s]' "killing pid $pid(ppid: $ppid, comm: $comm)" fail)" fi done < <(echo "$pid_info") [[ $succ == 0 ]] && break sleep 1 done } while read line; do log "$line" done |
知识点:
- while循环中修改外部的环境变量,则 不能使用管道的方式给while提供数据,这样的话,while 就是在新的子shell中执行的,不会影响到当前shell,所以:
- 使用了标准输入的重定向
- 使用了 <($cmd) 的方式
- 为了让字符串中连续的空格被保留,参数传递时多要通过双引号引上,即使是 $(cmd) 产生的字符串也要整个用双引号引上,当然,此时的双引号比较特殊,因为此时的双引号可以套双引号而不需要转义,示例: (注意下面几种双引号中嵌套单引号的的区别)
注意:
- 这个init进程是bash做的,如果docker attach的话,不管是ctrl-d退出还是ctrl-c退出,都会导致init进程终止,容器退出
- 脚本中的while循环最初想到的是通过sleep实现暂停的,但是考虑到sleep会产生一个额外的进程,不好看,于是选择了read;
注: 后来发现,使用read有一定好处,bash处理信号需要注意的是,在执行外部命令(如: sleep)时不能实时处理信号,只有在外部命令结束后才能处理信号; 而read虽然也是阻塞的,但是能实时处理信号