0

我正在使用子进程启动 snmpd,将对此的引用存储为全局变量,然后想稍后终止该进程。

我像这样开始这个过程:

snmp_proc = subprocess.Popen(['snmpd', '-p', pid_file,'-Lf', log_file],
                              stdout=open(os.devnull,'w'),stderr=subprocess.STDOUT)

这正确启动但似乎也创建了某种僵尸进程?ps ax 输出给出:

1716 ?        Z      0:00 [snmpd] <defunct>
1718 ?        S      0:00 snmpd -p /var/run/snmpd.pid -Lf /var/log/snmpd

现在,当我稍后尝试终止该进程时,只会终止已失效的僵尸进程,而另一个进程则保留。知道我做错了什么吗?这是停止 snmpd 的代码:

def stop_snmp(): 
    global snmp_proc
    if not snmp_proc:
        return 
    snmp_proc.terminate()
    snmp_proc.wait()
    snmp_proc = None
4

1 回答 1

2

<defunct>表示子进程已死,但您尚未读取其退出状态(使用snmp_proc.wait())。

我的猜测:snmpd启动一个守护进程(双叉等)并立即返回,即,为了避免僵尸,使用subprocess.check_call()而不是subprocess.Popen()这里。

要停止启动的守护程序服务,应该有一个特殊的命令。如果没有,则从中读取 pidpid_file并使用它向守护程序发送信号 ( os.kill()) 以杀死它。

我只是通过传递 -f 来禁用分叉解决了这个问题

是的,禁用守护程序行为是另一种选择。snmpd在这种情况下,在同一进程(由 启动Popen())中运行服务,因此它不应该成为僵尸,除非出现致命错误,例如,如果它无法启动。

于 2015-12-14T15:20:37.850 回答