V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Mrzhang0320
V2EX  ›  Python

做了一个监控 windows 程序进行重启的小玩意儿,遇到个 bug。。。

  •  
  •   Mrzhang0320 · 2018-02-28 09:47:24 +08:00 · 5649 次点击
    这是一个创建于 2461 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码 报错

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

    22 条回复    2018-02-28 16:04:24 +08:00
    octobersnow
        1
    octobersnow  
       2018-02-28 09:55:31 +08:00 via iPhone   ❤️ 1
    能来一张高清无码图吗
    Thanks
        2
    Thanks  
       2018-02-28 09:57:56 +08:00   ❤️ 1
    我没有做过相关的,猜测是下述原因:
    假设出错的 pid 为 x,那么获取 pids 时,x 在其中,但是之后进程 x 结束了(可能刚获取完就结束也可能遍历时结束),所以报错:找不到进程 x.
    加个 try 吧
    Mrzhang0320
        3
    Mrzhang0320  
    OP
       2018-02-28 10:00:51 +08:00
    @octobersnow 不好意思,新人,刚学会用语法上图片。。。
    Mrzhang0320
        4
    Mrzhang0320  
    OP
       2018-02-28 10:02:10 +08:00
    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)
    Mrzhang0320
        5
    Mrzhang0320  
    OP
       2018-02-28 10:02:57 +08:00
    Traceback (most recent call last):
    File "D:\python\lib\site-packages\psutil\_pswindows.py", line 635, in wrapper
    return fun(self, *args, **kwargs)
    File "D:\python\lib\site-packages\psutil\_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\__init__.py", line 368, in _init
    self.create_time()
    File "D:\python\lib\site-packages\psutil\__init__.py", line 699, in create_time
    self._create_time = self._proc.create_time()
    File "D:\python\lib\site-packages\psutil\_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\__init__.py", line 341, in __init__
    self._init(pid)
    File "D:\python\lib\site-packages\psutil\__init__.py", line 381, in _init
    raise NoSuchProcess(pid, None, msg)
    psutil._exceptions.NoSuchProcess: psutil.NoSuchProcess no process found with pid 11812
    ThinkZ
        6
    ThinkZ  
       2018-02-28 10:03:52 +08:00   ❤️ 1
    先确定你的 NoSuchProcess 是出在比较的时候,还是在 Kill 的时候.
    Mrzhang0320
        7
    Mrzhang0320  
    OP
       2018-02-28 10:06:00 +08:00
    @ThinkZ kill 完了,然后也重启启动了,之后就出现这样的
    Mrzhang0320
        8
    Mrzhang0320  
    OP
       2018-02-28 10:07:11 +08:00
    @ThinkZ 在上一次打印的 pids 中 这个不存在的进程 pid 还是有的
    Mrzhang0320
        9
    Mrzhang0320  
    OP
       2018-02-28 10:09:54 +08:00
    @Thanks 好的谢谢,我试一下加个 try ;确实在上一次打印 pids 时,存在这个 pid ;然后就出错了;
    kokutou
        10
    kokutou  
       2018-02-28 10:10:46 +08:00   ❤️ 1
    windows 批处理干这活很简单的。。。

    ```
    @echo off

    :start
    ping -n 3 127.0.0.1>nul
    tasklist | find /I "notepad.exe"
    if %errorlevel%==0 goto start
    ::start notepad.exe
    start cmd /c "notepad.exe"
    goto start
    ```
    ThinkZ
        11
    ThinkZ  
       2018-02-28 10:21:31 +08:00   ❤️ 1
    for pid in psutil.pids():
    p = psutil.Process(pid)

    for: 你获取了一个 pids 的列表, 这时当时的一个 pids 是一个状态, 并不代表着你在循环时 pids 列表里的 pid 会一直存在.
    ThinkZ
        12
    ThinkZ  
       2018-02-28 10:30:53 +08:00
    问题复现如下:
    >>> 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\_pswindows.py", line 636, in wrapper
    return fun(self, *args, **kwargs)
    File "C:\Python3\lib\site-packages\psutil\_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\__init__.py", line 428, in _init
    self.create_time()
    File "C:\Python3\lib\site-packages\psutil\__init__.py", line 754, in create_time
    self._create_time = self._proc.create_time()
    File "C:\Python3\lib\site-packages\psutil\_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\__init__.py", line 401, in __init__
    self._init(pid)
    File "C:\Python3\lib\site-packages\psutil\__init__.py", line 441, in _init
    raise NoSuchProcess(pid, None, msg)
    psutil.NoSuchProcess: psutil.NoSuchProcess no process found with pid 14988
    >>>
    skylancer
        13
    skylancer  
       2018-02-28 10:38:27 +08:00
    我实现的方式更简单..
    我直接获取需要监视进程的 PID,如果进程已经退 PID 肯定不存在返回的值一定小于 0
    Mrzhang0320
        14
    Mrzhang0320  
    OP
       2018-02-28 11:01:46 +08:00
    @ThinkZ 对诶
    Mrzhang0320
        15
    Mrzhang0320  
    OP
       2018-02-28 11:51:02 +08:00
    @skylancer 但是你怎么获取到那个 pid 呢,重启之后 pid 改变了
    shijingshijing
        16
    shijingshijing  
       2018-02-28 12:20:36 +08:00 via iPhone
    直接隔段时间就读取一次 windows 的开机时间不是更好么?不需要固定跑一个 process
    ioth
        17
    ioth  
       2018-02-28 12:23:09 +08:00
    看不清
    skylancer
        18
    skylancer  
       2018-02-28 13:58:54 +08:00
    @Mrzhang0320 你为什么一定要获得 PID 呢.. 你直接判定进程是否存在不就行了.. 换个思路来嘛
    geelaw
        19
    geelaw  
       2018-02-28 14:22:33 +08:00
    这方法太野鸡了

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

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

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

    @skylancer #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 。
    LeeSeoung
        20
    LeeSeoung  
       2018-02-28 14:51:50 +08:00
    - -你 kill 里的 pid 没有重新获取啊。。程序重启 pid 变了
    forestyuan
        21
    forestyuan  
       2018-02-28 15:25:41 +08:00
    如果要监控的程序是你自己的,可以通过进程间通信实现,不用这么麻烦
    skylancer
        22
    skylancer  
       2018-02-28 16:04:24 +08:00
    @geelaw 我的意思是,获取 a.exe 的 PID,不是直接取 PID,你就算被 b.exe 占了 PID 又有什么影响呢..
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2978 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 14:42 · PVG 22:42 · LAX 06:42 · JFK 09:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.