python可以写windows应用吗_【python】使用python写windows服务

背景

运维windows服务器的同学都知道,windows服务器进行批量管理的时候非常麻烦,没有比较顺手的工具,虽然saltstack和ansible都能够支持windows操作,但是使用起来总感觉不太舒服,比如ansible使用的winrm进行远程操作,需要提前在windows上进行设置,并且要求操作系统版本和powershell版本,根据个人使用经验,经常存在链接不上,连接慢,或者推送失败的问题,较高的失败率对于自动化运维体系的建立不利,所以与其受制于人,不如自己动手写一个agent,完全自己控制。

技术平台

服务器:windows服务器,测试过win2008r2、win2012、win7和win10.其他版本不知道怎么样。

开发语言:python

python模块:pywin32(python中的windows库),pyinstaller(用于将py文件生成exe程序),flask(web服务器)。以上三个模块都可以通过pip安装。以及一些python内置模块

优势:完全自己控制,根据自己需要开发功能。服务器端不需要安装任何其他依赖(不需要安装python环境,exe自带运行环境)

流程结构

1122522-20171220150129100-538581017.png

代码实现

agent的实现代码如下,代码有详细的注释,就不解释了。

ContractedBlock.gif

ExpandedBlockStart.gif

1 #-*- coding:utf-8 -*-

2 importwin32serviceutil3 importwin32service4 importwin32event5 from flask importFlask6 from flask importrequest7 importsys8 importos9 importzipfile10 importrequests11 importshutil12 importre13 importtime14 #设置编码

15 reload(sys)16 sys.setdefaultencoding('utf-8')17 ################################################################

18 ##########自定义函数区##########################################

19 ################################################################

20 #下载文件函数

21 defget_url_file(url):22 #下载到临时目录,如果临时目录不存在就创建一个

23 download_path = "D:\\tmp\\%s" %(time.time())24 ifos.path.exists(download_path):25 pass

26 else:27 os.makedirs(download_path)28 r = requests.get(url, stream=True)29 #解析文件名,如url为:http://www.ftp.com/test.zip那么文件名就是test.zip,并下载和写入文件

30 filename = "%s\\%s" % (download_path, url.split('/')[-1])31 with open(filename, "wb") as pdf:32 for chunk in r.iter_content(chunk_size=1024):33 ifchunk:34 pdf.write(chunk)35 return {'filename':filename,'download_path':download_path}36

37

38 defconfig_zabbix(hostname):39 #复制一份C:\\zabbix\\zabbix_agentd_win.conf.bak的zabbix模板文件,并修改其中的Hostname=new为新的hostname,然后生成新的配置文件。

40 try:41 open('C:\\zabbix\\zabbix_agentd_win.conf', 'w').write(re.sub(r'Hostname=new', 'Hostname=%s' % hostname, open('C:\\zabbix\\zabbix_agentd_win.conf.bak').read()))42 except:43 return "error"

44 #重启zabbix agent服务

45 service_list = os.popen('net start').read()46 if service_list.find('Zabbix Agent') == -1:47 try:48 os.system('net start "Zabbix Agent"')49 except:50 return "error"

51 else:52 try:53 os.system('net stop "Zabbix Agent')54 except:55 return "error"

56 try:57 os.system('net start "Zabbix Agent')58 except:59 return "error"

60 return "ok"

61

62

63 #加压缩文件函数

64 defun_zip(file_name,dest_path):65 zip_file =zipfile.ZipFile(file_name)66 file_pre = file_name.split('\\')[-1].split('.')[0]67 for names inzip_file.namelist():68 zip_file.extract(names, dest_path)69 zip_file.close()70 return (dest_path + '\\' +file_pre)71 ###################################################################

72 #############自定义函数区结束######################################

73 ###################################################################

74

75 #windows服务中显示的名字

76 classzlsService(win32serviceutil.ServiceFramework):77 _svc_name_ = 'zls_agent' ###可以根据自己喜好修改

78 _svc_display_name_ = 'zls_agent' ###可以根据自己喜好修改

79 _svc_description_ = 'zls_agent' ###可以根据自己喜好修改

80

81

82 def __init__(self,args):83 win32serviceutil.ServiceFramework.__init__(self,args)84 self.stop_event =win32event.CreateEvent(None, 0, 0, None)85 self.run =True86

87 defSvcDoRun(self):88 app = Flask(__name__)89 ##############################################################

90 #########flask路由设置区,自定义功能也放在这里################

91 ##############################################################

92 #推送文件服务,比如传入一个url和目标地址,装有本agent的客户端就会下载这个url并把文件放在指定位置

93 @app.route('/transferfile', methods=['GET', 'POST'])94 deftransferfile():95 if request.method == "GET":96 url = request.args.get('url')97 dest = request.args.get('dest')98 try:99 down_data =get_url_file(url)100 filename = down_data['filename']101 download_path = down_data['download_path']102 exceptBaseException, e:103 return "download url file error : %s" %e104 #加压缩文件

105 try:106 filepath =un_zip(filename,download_path)107 exceptBaseException, e:108 return "un zip error : %s" %e109 #删除压缩文件

110 try:111 os.remove(filename)112 except:113 pass

114 #复制文件内容到指定目录

115 try:116 shutil.copytree('%s' % filepath.replace('\\', '\\\\'), '%s' %dest)117 exceptBaseException, e:118 return "copy file error: %s" %e119 #d删除解压缩文件夹

120 try:121 shutil.rmtree(filepath.replace('\\', '\\\\'))122 except:123 pass

124 return "ok"

125 #修改配置文件路由,用来远程修改zabbix配置文件,比如curl http://server_ip:50000/zabbix?hostname="zabbix_agent"就会把位于服务器上的zabbix_agentd配置文件中的Hostname修改为Hostname=zabbix_agent。

126 @app.route('/zabbix', methods=['GET', 'POST'])127 defconfig_zabbix_func():128 if request.method == "GET":129 hostname = request.args.get('hostname')130 result =config_zabbix(hostname)131 returnresult132 #测试路由,用来测试agent是否正在运行,返回ok表示正在运行

133 @app.route('/', methods=['GET', 'POST'])134 deftest():135 if request.method == "GET":136 return "ok"

137 #使用flask自带的web服务器,监听本地所有地址的50000端口

138 ##############################################################

139 #############自定义功能区结束#################################

140 ##############################################################

141 app.run(host='0.0.0.0', port=50000)142 defSvcStop(self):143 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)144 win32event.SetEvent(self.stop_event)145 self.ReportServiceStatus(win32service.SERVICE_STOPPED)146 self.run =False147

148 if __name__ == '__main__':149 importsys150 importservicemanager151 if len(sys.argv) == 1:152 try:153 evtsrc_dll = os.path.abspath(servicemanager.__file__)154 servicemanager.PrepareToHostSingle(zlsService) #如果修改过名字,名字要统一

155 servicemanager.Initialize('zlsService',evtsrc_dll) #如果修改过名字,名字要统一

156 servicemanager.StartServiceCtrlDispatcher()157 exceptwin32service.error as details:158 importwinerror159 if details ==winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:160 win32serviceutil.usage()161 else:162 win32serviceutil.HandleCommandLine(zlsService) #如果修改过名字,名字要统一

View Code

生成exe程序

安装完成pyinstaller以后,打开命令行窗口

输入:pyinstaller -F windows_service.py

说明:-F表示生成一个单一的exe文件。其他选项使用pyinstaller --help查看。

1122522-20171220151203771-1797949283.png

执行完成后,提示生成exe程序

1122522-20171220151342646-241446106.png

找到这个程序

1122522-20171220151403287-1447161975.png

将程序复制到测试服务器上,安装

以管理员身份打开cmd,中输入 windows_servcie.exe install

1122522-20171220151450318-886314317.png

提示安装成功

1122522-20171220151609990-387179184.png

启动服务,然后设置成自动启动

1122522-20171220151715709-858756474.png

测试,浏览器中访问IP:50000端口,返回ok表示agent运行正常

1122522-20171220151823693-519428587.png

后续:

想要卸载服务,可以使用

1122522-20171220151930506-115999873.png

重要说明:

以上的测试,均在测试环境中进行,不要用在正式环境,因为这个agent没有加密通信,存在被人攻击的危险!!!

实际使用过程中,一定要对通信进行加密,可以使用https或者在命令中加入token,对token进行认证,只有正确的token才执行命令,或者使用rsa证书加密,这里就不再举例。

此agent只是给了三个示例性应用,实际用的时候,可以根据自己需要在函数区和路由定义区加入自己的程序,比如把这个agent做成监控系统,获取本地信息穿给服务端,在此抛砖引玉,剩下的就看自己的发挥了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值