为什么在 shell 脚本中调用 exec 时会生成失效进程?

why defunct process generate when call exec in shell script?

为什么在 shell 脚本中调用 exec 时会生成失效进程?

因为在启动 snmpd 之前应该设置和预加载一些额外的配置和 sharelib,

所以我像下面这样使用shell脚本,但问题是每次启动shell脚本时都会生成一个僵尸进程。

据我所知,exec会替换原来的shell进程26452,为什么子进程26453会生成僵尸?

$# ps -ef | grep snmpd
root     26452 12652  0 10:24 pts/4    00:00:00 snmpd udp:161,udp6:161 -f -Ln -I -system_mib ifTable -c /opt/snmp/config/snmpd.conf
root     26453 26452  0 10:24 pts/4    00:00:00 [snmpd_wapper.sh] <defunct>

如何避免僵尸进程,求助!

cat /home/xpeng/snmpd_wapper.sh
#!/bin/bash

 ( sleep 2;/opt/snmp/bin/snmpusm -v 3 -u myuser -l authNoPriv -a MD5 -A xpeng localhost create top myuser >/dev/null 2>&1; \
 /opt/snmp/bin/snmpvacm -v 3 -u myuser -l authNoPriv -a MD5 -A xpeng localhost createSec2Group 3 top RWGroup >/dev/null 2>&1; \
 /opt/snmp/bin/snmpvacm -v 3 -u myuser -l authNoPriv -a MD5 -A xpeng localhost createView all .1 80 >/dev/null 2>&1; \
 /opt/snmp/bin/snmpvacm -v 3 -u myuser -l authNoPriv -a MD5 -A xpeng localhost createAccess RWGroup 3 1 1 all all none >/dev/null 2>&1 ) &

 LIBRT=/usr/lib64
 if [ "$(. /etc/os-release; echo $NAME)" = "Ubuntu" ]; then
    LIBRT=/usr/lib/x86_64-linux-gnu
 fi
 echo $$>/tmp/snmpd.pid
 export LD_PRELOAD=$LD_PRELOAD:$LIBRT/librt.so:/opt/xpeng/lib/libxpengsnmp.so
 exec -a "snmpd" /opt/snmp/sbin/snmpd udp:161,udp6:161 -f -Ln -I -system_mib,ifTable -c /opt/snmp/config/snmpd.conf

对于任何 child 进程,parent 进程对 wait 负责。 child 进程从它死亡到它的 parent wait 秒将成为僵尸。

您启动了一个 child 进程,但随后您使用 exec 替换了 parent 进程。新程序不知道它有children,所以它没有wait。 child 因此成为僵尸,直到 parent 进程死亡。

这是一个 MCVE:

#!/bin/sh
sleep 1 &      # This process will become a zombie
exec sleep 30  # Because this executable won't `wait`

您可以改为 double fork:

#!/bin/sh
(             # Start a child shell
  sleep 1 &   # Start a grandchild process
)             # Child shell dies, grandchild is given to `init`
exec sleep 30 # This process now has no direct children