使用top工具,发现有大量僵尸进程
top - 05:32:34 up 6:21, 2 users, load average: 8.13, 6.15, 4.83
Tasks: 870 total, 1 running, 859 sleeping, 0 stopped, 10 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 94.2 id, 4.4 wa, 0.1 hi, 0.2 si, 0.0 st
MiB Mem : 127955.6 total, 106662.2 free, 16308.0 used, 5954.3 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 111647.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
354979 root 20 0 0 0 0 Z 0.0 0.0 0:00.03 git
355152 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 git
532213 root 20 0 0 0 0 Z 0.0 0.0 0:00.04 git
532326 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 git
541983 root 20 0 0 0 0 Z 0.0 0.0 0:00.03 git
542101 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 git
670442 root 20 0 0 0 0 Z 0.0 0.0 0:00.03 git
670528 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 git
672835 root 20 0 0 0 0 Z 0.0 0.0 0:00.04 git
#安装两个工具
[root@sc-midware-1 ~]# dnf install -y procps && dnf install psmisc -y
[root@sc-midware-1 ~]# pstree -apscl 354979
systemd,1 --switched-root --system --deserialize 31
└─containerd-shim,10835 -namespace k8s.io -id b8200d8cad653f1eeeae8afb7cd901b7d368a8b3381b4939563398075df8611c -address /run/containerd/containerd.sock
└─sleep,11681 --coreutils-prog-shebang=sleep /usr/bin/sleep 30000s
└─(git,354979)
发现僵尸进程是由expect调用git导致的
从网上找资料,发现expect退出的时候,需要等待杀死子进程,需要在expect中加入wait指令
function privateRepo(){
/usr/bin/expect <<EOF
set timeout -1
spawn git clone $repoUrl $localDir #意思是执行命令,expect内命令,shell中不存在
expect "Username*:"
send "$username\r"
expect "Password*:"
send "$password\r"
expect eof
wait ##必须要有啊
EOF
}
spawn命令实际上是运行了一个进程,并且这个进程是spawn的子进程,即spawn是一个父进程。 而close是用来关闭与spawn_id对应的子进程的连接,并且将子进程杀死。并且close在关闭连接后会返回一个数,系统会获得这个数以及子进程是怎么死的相关信息。
但是如果close后面没有wait的话,子进程虽然死了,但是依然存在进程列表中,此时这样的子进程叫做僵尸进程。僵尸进程会占用进程号,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。
所以wait说的专业一点是监视一个进程的终止。简单点就是负责给子进程收尸的。 原文链接:blog.csdn.net/a970973835/… 另外,close,wait可以隐含地产生。expect和interact都能检测到当前程序的退出,并隐含地执行一个close,但是wait只会在父进程退出时(即脚本退出时)隐含产生。所以对于只有一个子进程的脚本在exit后可以不写wait。 我怀疑在docker环境中,脚本执行完成后,spawn进程退出前,杀死了git子进程,但是子进程虽然死了,但是依然存在进程列表中,并且子进程的控制权交给了进程号为1的进程,即docker进程。此时这样的子进程叫做僵尸进程。 因为docker进程没有退出,那个spawn的子进程也不能成为孤儿进程被init进程当做孤儿进程回收(linux init进程号为1)。docker进程在linux系统中的进程号实际上不是1,所以,也就不能行使init进程的责任,回收孤儿进程。
[root@midware-0 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 10:51 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30000s
root 309 1 0 11:01 ? 00:00:00 [git] <defunct>
root 356 1 0 11:01 ? 00:00:00 [git] <defunct>
root 447 0 0 11:03 pts/1 00:00:00 /bin/bash
root 802 447 0 11:03 pts/1 00:00:00 ps -ef
[root@midware-0 /]# pstree -apscl 309
sleep,1 --coreutils-prog-shebang=sleep /usr/bin/sleep 30000s
└─(git,309)
经过测试,发现不再产生僵尸进程。 相关文章:www.cnblogs.com/anker/p/327… juejin.cn/post/728815…