- 1.背景
- 2.思路
- 3.僵尸进程回收方法
- 4.调用方法
在Python中使用 p = subprocess.Popen 执行 shell命令时,如果不使用 p.wait() ,就会产生僵尸进程,对于僵尸进程可以采用 os.wait(),os.waitpid()等方式回收,但是os.wait()是阻塞的,所以一般采用os.waitpid() 回收指定僵尸进程。
2.思路0.在主进程下启动一个线程,主管僵尸进程回收工作 1.先获取主进程下的所有子进程列表 2.再获取linux系统的所有僵尸进程列表 3.列表取交集,即是当前主进程下的僵尸子进程 4.然后对主进程下的僵尸子进程计入字典,key是僵尸子进程pid,value是计入子进程的时间戳 5.计算字典记录中僵尸子进程存活时间 6.如果超过阈值,则主动回收该子进程 7.循环回收3.僵尸进程回收方法
# -*- coding: utf-8 -*- """ Author: tanggaomeng date: 2021/11/20 Description: 回收僵尸子进程 1.只能回收主进程下面的僵尸子进程,对孙子、重孙子僵尸进程无法回收 2.如果想回收孙子、重孙子僵尸进程,需在子、孙子进程添加回收僵尸进程代码 """ import os import time import errno import commands import logging logging.basicConfig(format="%(asctime)s|%(levelname)s|%(filename)s:%(lineno)s|%(message)s", level=logging.DEBUG) # record the zombie process dictionary CHILD_ZOMBIE_DICT = {} # allow zombie process time to live: unit seconds ZOMBIE_TIME_TO_LIVE = 30 def get_child_zombie(parent_pid): """ get zombie child process that exceed the threshold record the zombie process dictionary: {"zombie process pid": "timestamp"} :param parent_pid: the current main process :return: the zombie process pid """ # 1.get a list of all child process of the current main process child_pid_cmd = "ps -ef | awk '{if($3==%s) print $2}' | sort | uniq" child_pid_list = commands.getoutput(child_pid_cmd % (parent_pid)) child_pid_list = child_pid_list.split("n") logging.info("main process [%s]: 1-child_pid_list: %s" % (parent_pid, child_pid_list)) # 2.get a list of all zombie processes on linux system node_zombie_cmd = "ps -A -ostat,pid | grep -e '^[Zz]' | awk '{print $2}'" node_zombie_list = commands.getoutput(node_zombie_cmd) node_zombie_list = node_zombie_list.split("n") logging.info("main process [%s]: 2-node_zombie_list: %s" % (parent_pid, node_zombie_list)) # 3.the intersection of the lists is the zombie child process under the current main process child_zombie_list = list(set(child_pid_list).intersection(node_zombie_list)) logging.info("main process [%s]: 3-child_zombie_list: %s" % (parent_pid, child_zombie_list)) global CHILD_ZOMBIE_DICT logging.info("main process [%s]: 4-CHILD_ZOMBIE_DICT: %s" % (parent_pid, CHILD_ZOMBIE_DICT)) if child_zombie_list: for child_zombie_pid in child_zombie_list: time_value = float(CHILD_ZOMBIE_DICT.get(child_zombie_pid, 0)) time_now = time.time() if time_value: # calculation time time_diff = round(time_now - time_value, 2) # recycling time exceeds the threshold child process if time_diff > ZOMBIE_TIME_TO_LIVE: CHILD_ZOMBIE_DICT.pop(child_zombie_pid) return child_zombie_pid else: CHILD_ZOMBIE_DICT[child_zombie_pid] = time_now return 0 else: # if there is no zombie process under the current main process, clear the record CHILD_ZOMBIE_DICT.clear() return 0 def wait_child(ppid): while True: try: # get the pid of the zombie child process that exceeds the threshold under the main process child_zombie_pid = get_child_zombie(ppid) if child_zombie_pid: logging.info("main process [%s]: 5-child_zombie_pid: %s" % (ppid, child_zombie_pid)) child_pid, status = os.waitpid(int(child_zombie_pid), os.WNOHANG) if child_pid == 0: # no child process was immediately available continue return_code = status >> 8 logging.info( "main process [%s]: child process: %s exit with return code: %s" % (ppid, child_pid, return_code)) else: continue except OSError as e: if e.errno == errno.ECHILD: logging.info("main process [%s]: no child process that need to wait" % (ppid)) else: logging.error("main process [%s] OSError: %s" % (ppid, e)) except Exception as e: logging.exception("main process [%s] Exception: %s" % (ppid, e)) finally: time.sleep(5)4.调用方法
# -*- coding: utf-8 -*- """ Author: tanggaomeng date: 2021/11/21 Description: """ import os import time import threading from recycling_zombie_processes import wait_child def main(): for i in range(0, 1000): time.sleep(5) if __name__ == '__main__': # recycling zombie processes ppid = os.getpid() thread = threading.Thread(target=wait_child, args=(ppid,)) thread.start() main()
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)