由来
最近在写一个服务器监控平台,python开发,前端标准bootstrap,后端Bottle, 数据库mongodb,要写服务器监控肯定少不了客户端了,客户端主要用到了XMLRPCServer, 服务端与客户端通过xml通信,这个在python的标准库里,还是可以信赖的,并且支持http验证,此处不赘言,以后再讲。linux上的客户端很好搞,因为linux自带python解释器,不管版本如何,使用起来还是很好改的, 最头疼的是window下的客户端,以前很少在win下做开发,python环境也是随意搭了一下,正使用的时候还是各种DT。。。
花了一段时间写了一个win下的python程序,不过依赖很多,包括pywin32、wmi,并且python的安装还需要改注册表,作为一个监控,如果还需要在服务器上安装python环境等东西有点得不偿失了。找到了pyinstaller和py2exe,能够将python程序打包成可执行的exe文件,复制到其他机器上可以直接执行,下面进入正题!
各种环境安装
- 安装pywin32、wmi弹框
Python version 2.7 required, which was not found in the registry
在注册表中找不到python,使用下面的一个脚本放在c盘根目录执行下就可以, 见Link
程序
# SmallestService.py
#
# A sample demonstrating the smallest possible service written in Python.
import win32serviceutil
import win32service
import win32event
class SmallestPythonService(win32serviceutil.ServiceFramework):
_svc_name_ = "SmallestPythonService"
_svc_display_name_ = "The smallest possible Python Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
# Create an event which we will use to wait on.
# The "service stop" request will set this event.
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
# Before we do anything, tell the SCM we are starting the stop process.
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
# And set my event.
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
# We do nothing other than wait to be stopped!
win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)
if __name__=='__main__':
win32serviceutil.HandleCommandLine(SmallestPythonService)
不过这样写好之后发现,直接运行脚本的确可以正常添加服务,添加的服务也可以正常操作,但是使用pyinstaller打包后的程序并不能正常执行。在pyinstaller的邮件列表找到了一个解决方案。 见 Link
具体细节不明了,需要改动的就是SvcDoRun方法和SvcStop两个方法。
因为RPCServer会一直阻塞线程,这里创建了一个子线程创建RPCServer,使用一个循环条件来控制线程的终结Link,这样不会导致window服务无法停止的问题。 需要在SvcStop方法最后加上所执行的程序的终结方法就可以。