Skip to content

进程管理

HouJie edited this page May 30, 2019 · 1 revision

Watch_Dogs-Client 进程管理

这一部分主要讲述如何实现进程管理的功能, 以下所有的示例代码和实现功能均在 Core/process_manage.py

进程关闭

思路1. 基于python的os模块

示例代码

    def kill_process(self, pid):
        """关闭进程"""
        try:
            if self.get_process_info(pid)['state'] == 'Z':  # zombie process
                raise ZombieProcess(pid)
            os.kill(int(pid), signal.SIGKILL)
        except OSError as e:
            if e.args[0] == 1:  # Operation not permitted
                raise AccessDenied(pid)
            if e.args[0] == 3:  # No such process
                raise NoSuchProcess(pid)

关闭该与该进程相关的所有进程
示例代码

    def kill_all_process(self, pid, kill_child=True, kill_process_gourp=True):
        """关闭进程 (pid所指进程, 该进程的子进程, 该进程的同组进程)"""
        # 获取需要关闭的进程
        self_pid = os.getpid()
        need_killed_process = [pid]
        if kill_child:
            need_killed_process.extend(self.get_all_child_process(pid))
        if kill_process_gourp and self.get_process_group_id(pid) != self.get_process_group_id(self_pid):
            need_killed_process.extend(self.get_same_group_process(self.get_process_group_id(pid)))
        need_killed_process = sorted(list(set(need_killed_process)), reverse=True)
        # 去掉监控进程本身 (因为启动进程会将启动的进程变成监控进程的子进程,这地方逻辑不是很清晰 todo:更好的进程关闭方式? )
        if self_pid in need_killed_process:
            need_killed_process.remove(self_pid)
        # 逐一关闭
        try:
            for p in need_killed_process:
                self.kill_process(p)
        except NoSuchProcess as e:
            pass

        return True

思路2. 基于ssh命令行方式

创建ssh链接demo

def remote_host_client(host, user, password, port):
    """连接远程客户端"""
    client = paramiko.SSHClient()  # 创建客户端
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        client.connect(hostname=host, port=port, username=user, password=password, timeout=3)
    except Exception as err:
        ssh_log.warning("连接远程主机 " + user + " @ " + host + "出现问题 : " + str(err))
        print "连接远程主机 " + user + " @ " + host + "出现问题 : " + str(err)
        client.close()
        return None
    return client

关闭进程

def kill_process(host, user, password, port, pid=None, process_name=None):
    """关闭进程"""
    res = {"status": "OK", "kill_pid": pid, "kill_process_name": process_name, "result": "",
           "comm": "kill -9 {pid}".format(pid=pid),
           "stdout": None, "stderr": None, }
    client = remote_host_client(host, user, password, port)
    if client and pid:
        try:
            stdin, stdout, stderr = client.exec_command(res["comm"])
            res["stdout"] = stdout.read()
            res["stderr"] = stderr.read()
        except Exception as err:
            res["status"] = "execute_error"
            res["error"] = str(err)
        client.close()
        return res
    else:
        res["status"] = "connect_error"
        return res

进程启动

思路1. 基于python的subprocess模块

    def start_process(self, execute_file_full_path):
        """后台创建一个新的进程(不随主进程退出,返回创建的进程号)"""
        # reference : https://stackoverflow.com/questions/1605520/how-to-launch-and-run-external-script-in-background
        # reference : https://www.cnblogs.com/zhoug2020/p/5079407.html
        # reference : https://stackoverflow.com/questions/89228/calling-an-external-command-in-python/92395#92395
        # reference : https://stackoverflow.com/questions/1196074/how-to-start-a-background-process-in-python

        # 获取执行文件相关地址
        cwd = execute_file_full_path[:execute_file_full_path.rindex("/")]
        execute_file = execute_file_full_path[execute_file_full_path.rindex("/") + 1:]
        # 启动进程
        if execute_file.endswith('.py'):  # python
            p = subprocess.Popen(["nohup", "python", execute_file_full_path],
                                 cwd=cwd,
                                 close_fds=True,
                                 stderr=subprocess.STDOUT)
            return p.pid
        # todo : support more execute file
        else:
            return False

思路2. 基于远程ssh命令行方式

def start_process(host, user, password, port, process_path=None, start_cmd=None):
    """远程执行命令,获取结果"""
    res = {"status": "OK", "process_path": process_path, "start_cmd": start_cmd}
    client = remote_host_client(host, user, password, port)
    if client:
        try:
            chan = client.invoke_shell()
            chan.send('cd {path}; {sc} \n'.format(path=process_path, sc=start_cmd))
            chan.recv(4096)
            time.sleep(1.3)
        except Exception as err:
            res["status"] = "execute_error"
            res["error"] = str(err)
        client.close()
        return res
    else:
        res["status"] = "connect_error"
        return res

进程重启

很简单, 重启 = 关闭 + 启动