Python 编写windows守护进程程序

简介


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


下面介绍两种实现方式。


第一种 监控进程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/
    执行命令
    E:\mywork\python\workspace\monitor>pyinstaller -w MonitorPid.py
    85 INFO: PyInstaller: 3.2.1
    85 INFO: Python: 3.5.4
    85 INFO: Platform: Windows-10-10.0.15063-SP0
    86 INFO: wrote E:\mywork\python\workspace\monitor\MonitorPid.spec
    87 INFO: UPX is not available.
    88 INFO: Extending PYTHONPATH with paths
    ['E:\\mywork\\python\\workspace\\monitor',
     'E:\\mywork\\python\\workspace\\monitor']
    88 INFO: checking Analysis
    102 INFO: checking PYZ
    113 INFO: checking PKG
    115 INFO: Building because toc changed
    115 INFO: Building PKG (CArchive) out00-PKG.pkg
    133 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
    137 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
    137 INFO: checking EXE
    137 INFO: Building because name changed
    137 INFO: Building EXE from out00-EXE.toc
    138 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\MonitorPid\MonitorPid.exe
    141 INFO: Building EXE from out00-EXE.toc completed successfully.
    144 INFO: checking COLLECT
    145 INFO: Building COLLECT out00-COLLECT.toc
    388 INFO: Building COLLECT out00-COLLECT.toc completed successfully.
    

    打包成功,杀毒软件会报警,选择找回文件或添加信任,下图是打包后程序


  5. 设置MonitorPid.exe到windows计划任务
    windows设置计划任务百度经验教程:http://jingyan.baidu.com/article/ca00d56c767cfae99febcf73.html
    贴出核心配置截图:

第二种监控进程名方式

  • 同第一种方式的第一步

  • pyInstaller 将Demo.py打包成DemoServer.exe
Python程序获取进程名称,最直接办法是打包成exe文件
E:\mywork\python\workspace\monitor>pyinstaller -w DemoServer.py
87 INFO: PyInstaller: 3.2.1
90 INFO: Python: 3.5.4
90 INFO: Platform: Windows-10-10.0.15063-SP0
93 INFO: wrote E:\mywork\python\workspace\monitor\DemoServer.spec
99 INFO: UPX is not available.
101 INFO: Extending PYTHONPATH with paths
['E:\\mywork\\python\\workspace\\monitor',
 'E:\\mywork\\python\\workspace\\monitor']
101 INFO: checking Analysis
101 INFO: Building Analysis because out00-Analysis.toc is non existent
102 INFO: Initializing module dependency graph...
103 INFO: Initializing module graph hooks...
104 INFO: Analyzing base_library.zip ...
2195 INFO: running Analysis out00-Analysis.toc
2196 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by e:\mywork\python\soft\python35\python.exe
2595 INFO: Caching module hooks...
2598 INFO: Analyzing E:\mywork\python\workspace\monitor\DemoServer.py
2825 INFO: Loading module hooks...
2826 INFO: Loading module hook "hook-encodings.py"...
2912 INFO: Loading module hook "hook-xml.py"...
3057 INFO: Loading module hook "hook-pywintypes.py"...
3288 INFO: Loading module hook "hook-pydoc.py"...
3304 INFO: Looking for ctypes DLLs
3304 INFO: Analyzing run-time hooks ...
3310 INFO: Looking for dynamic libraries
3556 INFO: Looking for eggs
3556 INFO: Using Python library e:\mywork\python\soft\python35\python35.dll
3556 INFO: Found binding redirects:
[]
3560 INFO: Warnings written to E:\mywork\python\workspace\monitor\build\DemoServer\warnDemoServer.txt
3568 INFO: checking PYZ
3568 INFO: Building PYZ because out00-PYZ.toc is non existent
3568 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz
3993 INFO: Building PYZ (ZlibArchive) E:\mywork\python\workspace\monitor\build\DemoServer\out00-PYZ.pyz completed successfully.
4009 INFO: checking PKG
4011 INFO: Building PKG because out00-PKG.toc is non existent
4012 INFO: Building PKG (CArchive) out00-PKG.pkg
4025 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
4028 INFO: Bootloader e:\mywork\python\soft\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
4028 INFO: checking EXE
4028 INFO: Building EXE because out00-EXE.toc is non existent
4028 INFO: Building EXE from out00-EXE.toc
4029 INFO: Appending archive to EXE E:\mywork\python\workspace\monitor\build\DemoServer\DemoServer.exe
4031 INFO: Building EXE from out00-EXE.toc completed successfully.
4036 INFO: checking COLLECT
4036 INFO: Building COLLECT because out00-COLLECT.toc is non existent
4039 INFO: Building COLLECT out00-COLLECT.toc
4378 INFO: Building COLLECT out00-COLLECT.toc completed successfully.

  • MonitorPidServer.py 程序
    监控系统所有进程名称,如果没有DemoServer.exe进程名称,执行命令DemoServer.exe
# -*- 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 MonitorServer:

    pidNotHandle = []
    servername = "DemoServer.exe"

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

    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 namevalue == self.servername:
                status = 1
                print("发现进程==============name=" + namevalue + ", pid=" + pidvalue + "\n")
                break

        if status == 0:  # 进程不存在,重新启动程序
            cmd = "E:/mywork/python/workspace/monitor/dist/DemoServer/" + self.servername
            os.popen(cmd)
            print("重启程序.............")

        print("ending.............")
        return 0


if __name__ == '__main__':
    MonitorServer().execute()


  • 同第一种方式的第四步

  • 同第一种方式的第五步

参考文章


python怎么获取windows服务的PID http://blog.csdn.net/ck3207/article/details/51955937


  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值