Python 编写windows守护进程程序

项目中使用python写一个监控程序,每隔5秒监控目录,发现文件就立刻FTP同步到另一台服务器。业务要求高实时性和高可用性。为了谨防程序崩溃,特别编写一个守护进程程序,时刻监控程序是否崩溃并重新启动。

转自:

https://blog.csdn.net/alex_bean/article/details/77923178

 

下面介绍两种实现方式。

 

第一种 监控进程PID方式

  1. Demo.py 10秒关闭程序,模拟程序崩溃
    # -*- coding: utf-8 -*-
    import logging
    import time
    import os
     
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename='e:/monitor/demo.log',
                        filemode='a')
     
     
    # Demo.py 10秒关闭程序,模拟程序崩溃
    # author 胖胖的alex 2017/09/10
    class Demo:
     
        pidlogpath = "e:/monitor/pid.run"
     
        def __init__(self):
            pass
     
        def setpid(self):  # 记录进程号PID
            fo = open(self.pidlogpath, "w")
            pid = str(os.getpid())
            fo.write(pid)
            fo.flush()
            fo.close()
            return pid
     
        def execute(self):
            pid = self.setpid()
            logging.info("启动程序,进程号:" + str(pid))
            i = 1
            while True:
                logging.info("pid = " + pid + " ---------- run " + str(i) + " s ")
                time.sleep(1)
                i += 1
                if i > 10:
                    break
            logging.info("程序关闭...")
     
     
    if __name__ == '__main__':
        Demo().execute()
    
    

     
  2. e:/monitor/pid.run 储存Demo.py进程号
     
  3. MonitorPid.py 监控windows系统所有进程任务
    定时任务执行,如果run.pid内进程号在系统中不存在,执行重启命令
    # -*- coding: utf-8 -*-
    import psutil
    import os
    import logging
     
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename='e:/monitor/monitor.log',
                        filemode='a')
     
    # PROCESS_RE = re.compile("pid=\d{1,4},\sname='\S{1,20}'") # 采用正则,获取数据 pid=x/xx/xxx/xxxx, name=[1~20个字符,
     
     
    # 监控windows系统所有进程服务任务。定时任务执行,发现run.pid进程号系统中不存在,执行命令python Demo.py启动程序
    # author 胖胖的alex 2017/09/1
    class Monitor:
     
        pidNotHandle = []
        pidlogpath = "e:/monitor/pid.run"
     
        def __init__(self):
            self.pidNotHandle = list(psutil.process_iter())  # 获取当前计算机的pid
     
        def getpid(self):  # 获取进程号PID
            fo = open(self.pidlogpath, "r")
            result = fo.read()
            fo.flush()
            fo.close()
            return result
     
        def execute(self):
            pid = []
            for each in self.pidNotHandle:
                a = str(each)  # each 是 class类型,可用type(each)查看类型
                # a 数据样式为:psutil.Process(pid=0, name='System Idle Process')
                pid.append(a[15:-1])  # 只取括号内部分;pid=0, name='System Idle Process'
     
            status = 0  # 被监控程序进程存在状态,0不存在,1存在
            for each in pid:
                nameposition = each.find("name")  # 获取name的位置;name='System Idle Process'
                namevalue = each[nameposition + 6:-1]  # 获取name值;System Idle Process
                pidposition = each.find("pid")
                pidvalue = each[pidposition + 4:nameposition-2]
                print("name="+namevalue + ", pid="+pidvalue+"\n")
     
                if pidvalue == self.getpid():
                    status = 1
                    print("发现进程==============name=" + namevalue + ", pid=" + pidvalue + "\n")
                    break
     
            if status == 0:  # 进程不存在,重新启动程序
                cmd = "python Demo.py"
                os.popen(cmd)
                print("重启程序.............")
     
            print("ending.............")
            return 0
     
     
    if __name__ == '__main__':
        Monitor().execute()
    
    
  4. pyInstaller 将MonitorPid.py程序生成monitor.exe文件
    pyInstaller百度经验:http://jingyan.baidu.com/article/a378c960b47034b3282830bb.html
    pyInstaller官方网站:http://www.pyinstaller.org/
    执行命令
     
    1. E:\mywork\python\workspace\monitor>pyinstaller -w MonitorPid.py

    2. 85 INFO: PyInstaller: 3.2.1

    3. 85 INFO: Python: 3.5.4

    4. 85 INFO: Platform: Windows-10-10.0.15063-SP0

    5. 86 INFO: wrote E:\mywork\python\workspace\monitor\MonitorPid.spec

    6. 87 INFO: UPX is not available.

    7. 88 INFO: Extending PYTHONPATH with paths

    8. ['E:\\mywork\\python\\workspace\\monitor',

    9. 'E:\\mywork\\python\\workspace\\monitor']

    10. 88 INFO: checking Analysis

    11. 102 INFO: checking PYZ

    12. 113 INFO: checking PKG

    13. 115 INFO: Building because toc changed

    14. 115 INFO: Building PKG (CArchive) out00-PKG.pkg

    15. 133 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.

    16. 137 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe

    17. 137 INFO: checking EXE

    18. 137 INFO: Building because name changed

    19. 137 INFO: Building EXE from out00-EXE.toc

    20. 138 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\MonitorPid\MonitorPid.exe

    21. 141 INFO: Building EXE from out00-EXE.toc completed successfully.

    22. 144 INFO: checking COLLECT

    23. 145 INFO: Building COLLECT out00-COLLECT.toc

    24. 388 INFO: Building COLLECT out00-COLLECT.toc completed successfully.


    打包成功,杀毒软件会报警,选择找回文件或添加信任,下图是打包后程序
    1. Python 编写windows守护进程程序_第1张图片
       
    2. 设置MonitorPid.exe到windows计划任务
      windows设置计划任务百度经验教程:http://jingyan.baidu.com/article/ca00d56c767cfae99febcf73.html
      贴出核心配置截图:
      Python 编写windows守护进程程序_第2张图片

    第二种监控进程名方式

    • 同第一种方式的第一步

     

    • pyInstaller 将Demo.py打包成DemoServer.exe

    Python程序获取进程名称,最直接办法是打包成exe文件

     
    1. E:\mywork\python\workspace\monitor>pyinstaller -w DemoServer.py

    2. 87 INFO: PyInstaller: 3.2.1

    3. 90 INFO: Python: 3.5.4

    4. 90 INFO: Platform: Windows-10-10.0.15063-SP0

    5. 93 INFO: wrote E:\mywork\python\workspace\monitor\DemoServer.spec

    6. 99 INFO: UPX is not available.

    7. 101 INFO: Extending PYTHONPATH with paths

    8. ['E:\\mywork\\python\\workspace\\monitor',

    9. 'E:\\mywork\\python\\workspace\\monitor']

    10. 101 INFO: checking Analysis

    11. 101 INFO: Building Analysis because out00-Analysis.toc is non existent

    12. 102 INFO: Initializing module dependency graph...

    13. 103 INFO: Initializing module graph hooks...

    14. 104 INFO: Analyzing base_library.zip ...

    15. 2195 INFO: running Analysis out00-Analysis.toc

    16. 2196 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable

    17. required by e:\mywork\python\soft\python35\python.exe

    18. 2595 INFO: Caching module hooks...

    19. 2598 INFO: Analyzing E:\mywork\python\workspace\monitor\DemoServer.py

    20. 2825 INFO: Loading module hooks...

    21. 2826 INFO: Loading module hook "hook-encodings.py"...

    22. 2912 INFO: Loading module hook "hook-xml.py"...

    23. 3057 INFO: Loading module hook "hook-pywintypes.py"...

    24. 3288 INFO: Loading module hook "hook-pydoc.py"...

    25. 3304 INFO: Looking for ctypes DLLs

    26. 3304 INFO: Analyzing run-time hooks ...

    27. 3310 INFO: Looking for dynamic libraries

    28. 3556 INFO: Looking for eggs

    29. 3556 INFO: Using Python library e:\mywork\python\soft\python35\python35.dll

    30. 3556 INFO: Found binding redirects:

    31. []

    32. 3560 INFO: Warnings written to E:\mywork\python\workspace\monitor\build\DemoServer\warnDemoServer.txt

    33. 3568 INFO: checking PYZ

    34. 3568 INFO: Building PYZ because out00-PYZ.toc is non existent

    35. 3568 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz

    36. 3993 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz completed successfully.

    37. 4009 INFO: checking PKG

    38. 4011 INFO: Building PKG because out00-PKG.toc is non existent

    39. 4012 INFO: Building PKG (CArchive) out00-PKG.pkg

    40. 4025 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.

    41. 4028 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe

    42. 4028 INFO: checking EXE

    43. 4028 INFO: Building EXE because out00-EXE.toc is non existent

    44. 4028 INFO: Building EXE from out00-EXE.toc

    45. 4029 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\DemoServer\DemoServer.exe

    46. 4031 INFO: Building EXE from out00-EXE.toc completed successfully.

    47. 4036 INFO: checking COLLECT

    48. 4036 INFO: Building COLLECT because out00-COLLECT.toc is non existent

    49. 4039 INFO: Building COLLECT out00-COLLECT.toc

    50. 4378 INFO: Building COLLECT out00-COLLECT.toc completed successfully.

    Python 编写windows守护进程程序_第3张图片
    • MonitorPidServer.py 程序
      监控系统所有进程名称,如果没有DemoServer.exe进程名称,执行命令DemoServer.exe
     
    1. # -*- coding: utf-8 -*-

    2. import psutil

    3. import os

    4. import logging

    5.  
    6. logging.basicConfig(level=logging.INFO,

    7. format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',

    8. datefmt='%a, %d %b %Y %H:%M:%S',

    9. filename='e:/monitor/monitor.log',

    10. filemode='a')

    11.  
    12. # PROCESS_RE = re.compile("pid=\d{1,4},\sname='\S{1,20}'") # 采用正则,获取数据 pid=x/xx/xxx/xxxx, name=[1~20个字符,

    13.  
    14.  
    15. # 监控windows系统所有进程服务任务。定时任务执行,发现run.pid进程号系统中不存在,执行命令python Demo.py启动程序

    16. # author 胖胖的alex 2017/09/1

    17. class MonitorServer:

    18.  
    19. pidNotHandle = []

    20. servername = "DemoServer.exe"

    21.  
    22. def __init__(self):

    23. self.pidNotHandle = list(psutil.process_iter()) # 获取当前计算机的pid

    24.  
    25. def execute(self):

    26. pid = []

    27. for each in self.pidNotHandle:

    28. a = str(each) # each 是 class类型,可用type(each)查看类型

    29. # a 数据样式为:psutil.Process(pid=0, name='System Idle Process')

    30. pid.append(a[15:-1]) # 只取括号内部分;pid=0, name='System Idle Process'

    31.  
    32. status = 0 # 被监控程序进程存在状态,0不存在,1存在

    33. for each in pid:

    34. nameposition = each.find("name") # 获取name的位置;name='System Idle Process'

    35. namevalue = each[nameposition + 6:-1] # 获取name值;System Idle Process

    36. pidposition = each.find("pid")

    37. pidvalue = each[pidposition + 4:nameposition-2]

    38. print("name="+namevalue + ", pid="+pidvalue+"\n")

    39.  
    40. if namevalue == self.servername:

    41. status = 1

    42. print("发现进程==============name=" + namevalue + ", pid=" + pidvalue + "\n")

    43. break

    44.  
    45. if status == 0: # 进程不存在,重新启动程序

    46. cmd = "E:/mywork/python/workspace/monitor/dist/DemoServer/" + self.servername

    47. os.popen(cmd)

    48. print("重启程序.............")

    49.  
    50. print("ending.............")

    51. return 0

    52.  
    53.  
    54. if __name__ == '__main__':

    55. MonitorServer().execute()

     
    • 同第一种方式的第四步
       
    • 同第一种方式的第五步

你可能感兴趣的:(python)