Python中如何监控Windows程序并自动重启,遇到bug怎么解决?

代码 报错

这种情况不固定出现,有时候运行几次就出现了,有时候运行几十次才出现,各位大佬求解


Python中如何监控Windows程序并自动重启,遇到bug怎么解决?

22 回复
import psutil
import subprocess
import time
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('monitor.log'),
        logging.StreamHandler()
    ]
)

class ProcessMonitor:
    def __init__(self, process_name, exe_path):
        """
        :param process_name: 要监控的进程名(如: notepad.exe)
        :param exe_path: 程序可执行文件完整路径
        """
        self.process_name = process_name.lower()
        self.exe_path = exe_path
        self.process = None
        
    def is_process_running(self):
        """检查进程是否在运行"""
        for proc in psutil.process_iter(['name']):
            try:
                if proc.info['name'].lower() == self.process_name:
                    return proc
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                pass
        return None
    
    def start_process(self):
        """启动程序"""
        try:
            self.process = subprocess.Popen(self.exe_path)
            logging.info(f"已启动进程: {self.process_name}")
            return True
        except Exception as e:
            logging.error(f"启动进程失败: {e}")
            return False
    
    def monitor(self, check_interval=5):
        """监控主循环"""
        logging.info(f"开始监控进程: {self.process_name}")
        
        while True:
            try:
                current_proc = self.is_process_running()
                
                if not current_proc:
                    logging.warning(f"进程 {self.process_name} 未运行,正在重启...")
                    if not self.start_process():
                        logging.error("重启失败,等待下次检查")
                else:
                    # 检查进程状态
                    try:
                        status = current_proc.status()
                        if status == psutil.STATUS_ZOMBIE:
                            logging.warning(f"进程 {self.process_name} 处于僵尸状态,准备重启...")
                            current_proc.terminate()
                            time.sleep(2)
                            self.start_process()
                    except:
                        pass
                
                time.sleep(check_interval)
                
            except KeyboardInterrupt:
                logging.info("监控程序已停止")
                break
            except Exception as e:
                logging.error(f"监控出错: {e}")
                time.sleep(check_interval)

# 使用示例
if __name__ == "__main__":
    # 配置要监控的程序
    monitor = ProcessMonitor(
        process_name="notepad.exe",  # 进程名
        exe_path="C:\\Windows\\System32\\notepad.exe"  # 程序路径
    )
    
    # 开始监控,每10秒检查一次
    monitor.monitor(check_interval=10)

核心要点:

  1. 进程检测:用psutil遍历系统进程,匹配进程名
  2. 状态监控:检查进程是否存在,以及是否处于僵尸状态
  3. 自动重启:进程消失时用subprocess.Popen()重新启动
  4. 异常处理:捕获权限异常、进程异常等
  5. 日志记录:所有操作记录到日志文件,方便排查

遇到bug的解决方法:

  • 权限问题:用管理员权限运行监控脚本
  • 路径问题:确保exe_path是完整路径且存在
  • 进程名匹配:Windows进程名带.exe后缀
  • 资源占用:合理设置检查间隔,避免CPU过高

一句话建议: 用psutil监控进程状态,subprocess实现重启,加日志记录方便排查。


我没有做过相关的,猜测是下述原因:
假设出错的 pid 为 x,那么获取 pids 时,x 在其中,但是之后进程 x 结束了(可能刚获取完就结束也可能遍历时结束),所以报错:找不到进程 x.
加个 try 吧

不好意思,新人,刚学会用语法上图片。。。

import os,psutil,time,signal

ProList = []
i = 0
ProcessName = “1.exe"
ProgramPath = r"E:\test\1.exe”

#检测并启动进程
def main():
print(psutil.pids())
for pid in psutil.pids():
p = psutil.Process(pid)
ProList.append(str(p.name()))
if p.name() == ProcessName:
kill(pid)
print(“111”)

def kill(pid):
try:
print(“killing Server…”)
os.kill(pid, signal.SIGTERM)
time.sleep(6)
print(“Restart Server Success…”)
os.startfile(ProgramPath)
print(pid)
except e:
print(“没有%s 进程” % pid)

if name==“main”:
while True:
main()
i = i+1
print(i)
time.sleep(3)

Traceback (most recent call last):
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 635, in wrapper
return fun(self, *args, **kwargs)
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 821, in create_time
return cext.proc_create_time(self.pid)
ProcessLookupError: [Errno 3] No such process

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 368, in _init
self.create_time()
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 699, in create_time
self._create_time = self._proc.create_time()
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 640, in wrapper
raise NoSuchProcess(self.pid, self._name)
psutil._exceptions.NoSuchProcess: psutil.NoSuchProcess process no longer exists (pid=11812)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “jiankong.py”, line 40, in <module>
main()
File “jiankong.py”, line 12, in main
p = psutil.Process(pid)
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 341, in init
self._init(pid)
File “D:\python\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 381, in _init
raise NoSuchProcess(pid, None, msg)
psutil._exceptions.NoSuchProcess: psutil.NoSuchProcess no process found with pid 11812

先确定你的 NoSuchProcess 是出在比较的时候,还是在 Kill 的时候.

kill 完了,然后也重启启动了,之后就出现这样的

在上一次打印的 pids 中 这个不存在的进程 pid 还是有的

好的谢谢,我试一下加个 try ;确实在上一次打印 pids 时,存在这个 pid ;然后就出错了;

windows 批处理干这活很简单的。。。

<br> off<br><br>:start<br>ping -n 3 127.0.0.1&gt;nul<br>tasklist | find /I "notepad.exe"<br>if %errorlevel%==0 goto start<br>::start notepad.exe<br>start cmd /c "notepad.exe"<br>goto start<br>

for pid in psutil.pids():
p = psutil.Process(pid)

for: 你获取了一个 pids 的列表, 这时当时的一个 pids 是一个状态, 并不代表着你在循环时 pids 列表里的 pid 会一直存在.

问题复现如下:
>>> a = psutil.pids()
>>> a
[0, 4, 396, 516, 612, 764, 772, 860, 916, 332, 464, 512, 972, 1112, 1164, 1296, 1564, 1784, 1908, 1968, 2064, 2148, 2192, 2280, 2412, 2556, 2564, 2572, 2580, 2588, 2668, 2708, 2788, 2796, 2804, 2872, 2884, 2900, 2460, 3236, 3780, 4376, 5352, 5684, 2684, 2180, 6060, 488, 2616, 1244, 2692, 4356, 5972, 3516, 5960, 1984, 3452, 6496, 6628, 7812, 7872, 7976, 8052, 8076, 8096, 8120, 8148, 8160, 1744, 7508, 7720, 7744, 8072, 2376, 7436, 8220, 9088, 9128, 8508, 8412, 12188, 3484, 3680, 5928, 5348, 7588, 16352, 5872, 604, 15716, 7028, 16168, 12880, 15220, 11432, 14988, 100, 15564, 12856, 16796, 7064, 17356, 16028, 10380, 14980, 9864, 14776, 16064, 17028, 728, 9792, 8024, 15304, 14760, 17196, 13072, 12244, 13712, 9876, 16876, 11956, 6556, 11608, 13080, 16892, 15456, 8156, 11664, 12792, 6248, 14940, 16188, 15324, 1000, 16212, 7752, 13520, 12328, 4724]
>>> type (a)
<class ‘list’>

# 这里手工 KILL 掉 14988 进程, 模拟被其它程序关闭…etc


>>> psutil.Process(14988)
Traceback (most recent call last):
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 636, in wrapper
return fun(self, *args, **kwargs)
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 822, in create_time
return cext.proc_create_time(self.pid)
ProcessLookupError: [Errno 3] No such process

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 428, in _init
self.create_time()
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 754, in create_time
self._create_time = self._proc.create_time()
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://_pswindows.py” rel=“nofollow noopener”>_pswindows.py", line 641, in wrapper
raise NoSuchProcess(self.pid, self._name)
psutil.NoSuchProcess: psutil.NoSuchProcess process no longer exists (pid=14988)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “<pyshell#5>”, line 1, in <module>
psutil.Process(14988)
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 401, in init
self._init(pid)
File “C:\Python3\lib\site-packages\psutil<a target=”_blank" href=“http://init.py” rel=“nofollow noopener”>init.py", line 441, in _init
raise NoSuchProcess(pid, None, msg)
psutil.NoSuchProcess: psutil.NoSuchProcess no process found with pid 14988
>>>

我实现的方式更简单…
我直接获取需要监视进程的 PID,如果进程已经退 PID 肯定不存在返回的值一定小于 0

但是你怎么获取到那个 pid 呢,重启之后 pid 改变了

直接隔段时间就读取一次 windows 的开机时间不是更好么?不需要固定跑一个 process

看不清

你为什么一定要获得 PID 呢… 你直接判定进程是否存在不就行了… 换个思路来嘛

这方法太野鸡了

po 主的问题答案很简单,因为你得到的 PID 是“刚刚存在的进程的 PID ”,过一会儿就可能没有了。尤其是,当你枚举到那个 PID 之前走过 kill 的代码路径的话,你需要等待好几秒,这非常容易导致刚刚那个 PID 的进程已经没有了。

接下来说说 2 个之前的错误:

#6 kill 被 try-catch 包裹,不可能在 console 输出该异常

#13 一个进程结束之后,如果该进程的内核对象已经被释放,则它的 PID 可以被重用。不能这样去判断一个进程是否已经结束。


另外从代码我实在猜不出来 po 主的代码有什么“有意义”的用途,如果我没理解错,这段代码是想:

循环结束所有的 1.exe ,并用对每个结束的 1.exe 都启动一个 E:\test\1.exe 代替之。循环这样做,导致每个重新启动的 1.exe 都会被再次 kill 并启动。

如果总共有 k 个 1.exe ,那么一个 1.exe 能存活不超过 6k+O(1) 秒。

考虑只有一个 1.exe 的情况,我看不出为什么要不断杀掉、等 6 秒再重启 1.exe 。

  • -你 kill 里的 pid 没有重新获取啊。。程序重启 pid 变了

如果要监控的程序是你自己的,可以通过进程间通信实现,不用这么麻烦

我的意思是,获取 a.exe 的 PID,不是直接取 PID,你就算被 b.exe 占了 PID 又有什么影响呢…

回到顶部