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

2018-02-28 09:47:24 +08:00
 Mrzhang0320

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

5476 次点击
所在节点    Python
22 条回复
octobersnow
2018-02-28 09:55:31 +08:00
能来一张高清无码图吗
Thanks
2018-02-28 09:57:56 +08:00
我没有做过相关的,猜测是下述原因:
假设出错的 pid 为 x,那么获取 pids 时,x 在其中,但是之后进程 x 结束了(可能刚获取完就结束也可能遍历时结束),所以报错:找不到进程 x.
加个 try 吧
Mrzhang0320
2018-02-28 10:00:51 +08:00
@octobersnow 不好意思,新人,刚学会用语法上图片。。。
Mrzhang0320
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
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
2018-02-28 10:03:52 +08:00
先确定你的 NoSuchProcess 是出在比较的时候,还是在 Kill 的时候.
Mrzhang0320
2018-02-28 10:06:00 +08:00
@ThinkZ kill 完了,然后也重启启动了,之后就出现这样的
Mrzhang0320
2018-02-28 10:07:11 +08:00
@ThinkZ 在上一次打印的 pids 中 这个不存在的进程 pid 还是有的
Mrzhang0320
2018-02-28 10:09:54 +08:00
@Thanks 好的谢谢,我试一下加个 try ;确实在上一次打印 pids 时,存在这个 pid ;然后就出错了;
kokutou
2018-02-28 10:10:46 +08:00
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
2018-02-28 10:21:31 +08:00
for pid in psutil.pids():
p = psutil.Process(pid)

for: 你获取了一个 pids 的列表, 这时当时的一个 pids 是一个状态, 并不代表着你在循环时 pids 列表里的 pid 会一直存在.
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
2018-02-28 10:38:27 +08:00
我实现的方式更简单..
我直接获取需要监视进程的 PID,如果进程已经退 PID 肯定不存在返回的值一定小于 0
Mrzhang0320
2018-02-28 11:01:46 +08:00
@ThinkZ 对诶
Mrzhang0320
2018-02-28 11:51:02 +08:00
@skylancer 但是你怎么获取到那个 pid 呢,重启之后 pid 改变了
shijingshijing
2018-02-28 12:20:36 +08:00
直接隔段时间就读取一次 windows 的开机时间不是更好么?不需要固定跑一个 process
ioth
2018-02-28 12:23:09 +08:00
看不清
skylancer
2018-02-28 13:58:54 +08:00
@Mrzhang0320 你为什么一定要获得 PID 呢.. 你直接判定进程是否存在不就行了.. 换个思路来嘛
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
2018-02-28 14:51:50 +08:00
- -你 kill 里的 pid 没有重新获取啊。。程序重启 pid 变了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/433365

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX