工作中经常要和服务器、数据库这些打交道,有些小功能例如:服务监控、数据监控等用java往往无处下手,即使能做也要花费很长的时间,身边好几个同事都会Python,面对这些需求他们往往优先选择Python来实现,又快又省事。所以我也计划着自学一下Python,寻思着买一本入门的书来参考,在豆瓣上挑来挑去最后挑了《Head first Python》这本。买来后断断续续看了好几章了,对Python也有了一些基本的了解,不过一直没真正上手。
废话太多,直接步入正题,昨天领导让我写个脚本来实时监控某个服务的日志,监控日志中报出的用户购买超时的现象,如果某个node累计超时次数达到10次则通过邮件和短信告警。
需求就是上面说的这样,虽然Python用的还不熟练,不过当下也没其它好的方式来实现,没办法,赶鸭子上架,现学现用,如果碰到不会的就借助于万能的互联网吧
一、Python调用shell
首先考虑实现的方式,由于领导要求实时监控,所以当前想到的方式就是使用linux shell的tail命令扫描服务日志,然后再使用关键字来grep,根据grep出来的日志内容进行分析。这时候碰到了第一个问题,如何在Python中执行linux shell命令呢?
没办法,上网求助,网上有人推荐使用os.system,不过大部分都推荐使用subprocess模块来实现,通过官方文档说明,我决定使用subprocess
官方给出的文档里有这么一段话:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
翻译过来的意思大致就是:subprocess模块允许你新建子进程,可以连接到进程的输入、输出、异常通道,并且可以获取到子进程的返回值,这个模块是Python用来替代一些其它过时的模块和功能的。
所以说,官方推荐使用subprocess来实现类似的功能。
要使用subprocess,首先必须import该模块
import subprocess
要调用shell命令,subprocess有很多方式,比如call、Popen等,这里我们使用Popen
首先看一个最简单的实例:
subprocess.Popen('ls -l',stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
上面的代码构建了一个Popen对象,Popen的构造函数格式如下:
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
参数args可以是字符串或者序列类型(如:list,元组),用于指定进程的可执行文件及其参数。如果是序列类型,第一个元素通常是可执行文件的路径。
参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。
如果参数shell设为true,程序将通过shell来执行。
关于其它具体的参数的说明,参见官方文档:http://docs.python.org/2/library/subprocess.html#popen-constructor
不想看英文的可以看网上的另一篇博客:http://blog.csdn.net/wuwangyingzhong/article/details/6002055
我的代码逻辑如下:
#日志文件目录和名称 filename = '/home/project/logs/xxx.log' #要执行的shell命令 command='tail -f '+filename+'|grep "timeout"' popen=subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True) while True: #获取当前grep出来的日志文本行 line=popen.stdout.readline().strip() #对日志文本进行分析(这里省略)
二、Python发送http请求
上面已经提到,告警的方式为邮件和短信,我们的短信推送接口是一个http接口,所以如果需要短信告警,则需要通过python来请求该http接口。python中一共有urllib、urllib2、httplib、httplib2支持发送http请求,由于服务器上没有安装python的httplib和httplib2模块,所以只能使用urllib,urllib2
使用GET请求来请求短信推送接口,可以把参数写在url中,如果使用POST方式来请求接口,则数据必须放在data或者body中,不能放在url中,放在url中将被忽略。
附上一个通过urllib,urllib2发送GET请求的示例:
import urllib,urllib2 def main(): url="http://www.baidu.com/s?wd=douban" req = urllib2.Request(url) print req res_data = urllib2.urlopen(req) res = res_data.read() print res if __name__ == '__main__': main()
关于python对http请求的操作,可以参见博客:http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201231085444250/
三、脚本进程和子进程的退出
发现了2个问题:
问题1:在上面的代码中,python调用的shell tail命令作用是实时监控当前的日志,而服务是24小时不间断的,该python脚本也一直同步执行,所以只能使用nohup方式后台启动。每次要关闭该脚本,手动通过进程pid来kill。带来了一个新的问题,每次kill掉python主进程时,主进程执行时启动的Popen子进程未关闭,由于调试时曾经连续启动->kill->启动->kill多次,导致系统中出现了一大堆tail日志的进程,这是我原来没有预料到的。
问题2:我们的日志是生成的dailyRolling日志,文件名称为:xxx_dailyRolling.log,每天的0点会自动重命名为xxx_dailyRolling.logyyyyMMdd,yyyyMMdd代表前一天的日期,例如xxx_dailyRolling.log20131023,如果tail -f xxx_dailyRolling.log命令一直执行,到0点时会中断,所以我还需要在每天0点前停止当前的python脚本,然后在第二天0点后定时启动此python脚本
综上,2个问题一起解决,在0点前停止python脚本前先kill掉Popen子进程,然后再停止就OK了。
我的思路时每天设置一个固定的时间点,例如就定为每天的23:30:00(因为我们的服务在凌晨时基本上没人使用,监控的目的主要是为了监控白天高峰期时的服务情况,所以23:30到0点这段时间即使没监控也不影响),然后在Popen子进程执行时判断当前时刻是否到了23:30:00,如果已经到了,则终止子进程。通过实践证明,如果Popen子进程终止了,如果python主进程里没有挂起的其余子进程在执行,则主进程也会终止。
Popen可以通过terminate()或者kill()函数来终止当前的子进程。在执行了terminate()后,如果不想立即终止,可以通过wait()或poll()函数来等待子进程执行结束,关于各函数的使用,具体参考官方文档。
各函数说明如下:
Check if child process has terminated. Set and return returncode attribute.
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Popen.terminate()
Stop the child. On Posix OSs the method sends SIGTERM to the child. On Windows the Win32 API function TerminateProcess() is called to stop the child.
Popen.kill()
Kills the child. On Posix OSs the function sends SIGKILL to the child. On Windows kill() is an alias for terminate().
附上一个示例:
#程序执行终止时间为当前时刻延迟15秒 stoptime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()+15)) def main(): popen=subprocess.Popen(command,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True) pid=popen.pid print('Popen.pid:'+str(pid)) while True: line=popen.stdout.readline().strip() print(line) #当前时间 thistime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) if thistime>=stoptime: #终止子进程 popen.terminate() #等待子进程终止后跳出while循环 if subprocess.Popen.poll(popen) is not None: break else: print('waiting for subprocess.Popen terminate()') print('DONE') if __name__ == '__main__': main()
四、Python2.x和3.x版本的区别(部分)
Python在2.x和3.x之间有一些特性区别比较大,由于我本地是安装的最新的3.2.2版本,而服务器上还是2.6.x,所以在编写调试时遇到了一些,也拿出来说说说:
区别1.print函数
在python 2.x版本中,同时支持print(xxx)和print xxx,示例:
>>> name='chenzhou' >>> print name chenzhou >>> print(name) chenzhou >>>
在python 3.x版本中,只支持print(xxx)的方式,示例:
>>> name='chenzhou' >>> print(name) chenzhou >>> print name SyntaxError: invalid syntax >>>
区别2.判断字典中的key是否存在
在python 2.x中,可以使用has_key(key)函数,也可以判断 key in xxxMap.keys(),示例:
>>> users={'name':'chenzhou','age':'24','address':'Beijing'} >>> print users.has_key('name') True >>> print 'name' in users.keys() True >>> print users.has_key('score') False >>> print 'score' not in users.keys() True >>>
在python 3.x中,只支持key in xxxMap.keys() 示例:
>>> users={'name':'chenzhou','age':'24','address':'Beijing'} >>> print('name' in users.keys()) True >>> print('score' in users.keys()) False >>> print(users.has_key('name')) Traceback (most recent call last): File "<pyshell#20>", line 1, in <module> print(users.has_key('name')) AttributeError: 'dict' object has no attribute 'has_key' >>>
五、Python UnicodeDecodeError
脚本写完后在linux下执行时报错:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)
网友给出的原因是windows系统下编辑的文件在linux下编码转换出现的问题,具体解决方法如下:
#引入sys模块 import sys #加入下面两行代码 reload(sys) sys.setdefaultencoding('utf-8')
其它:
在grep关键字时用到了正则表达式,推荐一篇关于Python正则表达式的好博客:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
Python官网:http://www.python.org/
以上就是我第一次使用Python的经历,开始体会到了Python的优势。另外,也应了那句俗话,学习编程语言,光看书是没有效果的,只有理论与实践结合起来才能达到学习的效果,我想这应该就是别人经常提到的应用驱动学习吧。
最后,说明一下,我只是一个Python小菜鸟,写的东西很简单,大家不喜勿喷哈。
相关推荐
总结,这个"python学习资料python脚本实现监控apache,并使用mail发送报警共2页.pdf.zip"的资源提供了一个学习如何结合Python、系统监控和邮件通知的实践案例。通过学习和实践这个案例,你可以掌握如何利用Python进行...
总的来说,这个项目提供了一个全面的软硬件监控解决方案,利用Python3.6.5的`psutils`库获取系统信息,通过Redis存储和传输数据,以JSON格式标准化输出,所有操作都在离线环境下完成,确保了数据的安全性和独立性。...
在Linux环境中,使用Python进行服务器监控是一种常见的实践,因为它提供了丰富的库和简洁的语法,使得开发监控脚本变得容易。在本文中,我们将深入探讨如何利用Python2.7来编写针对Linux服务器的监控脚本,重点关注...
在IT行业中,Python是一种广泛应用的编程语言,尤其在自动化任务和数据处理方面表现突出。大麦网抢票脚本就是利用Python的这种特性,通过...对于想要学习Python编程或者对自动化感兴趣的用户,这是一个很好的实践项目。
通过以上分析,我们可以看出"脚本+python安装包+使用说明.rar"这个压缩包是一个包含Python编程、自动化脚本应用的实践案例,旨在帮助用户提升抢购茅台的效率。但同时,使用这类工具也需要谨慎,遵循合法、道德的使用...
总之,这个压缩包是一个配套的教学资源,旨在帮助学习者通过Python实践量化交易,理解其背后的逻辑和步骤。通过深入学习和应用这些代码,你可以提升自己的数据分析能力,构建并优化属于自己的量化交易系统。
【微信跳一跳自动脚本Python实现】 微信跳一跳是一款广受欢迎的微信小程序游戏,玩家需要控制小人精准跳跃到下一个方块上,积累分数。为了帮助玩家更好地理解和掌握Python编程,我们可以创建一个自动脚本来模拟游戏...
标题中的“Python-用Python写的一个查询旁站的脚本”揭示了我们即将探讨的主题是使用Python编程语言编写的用于查询“旁站”(可能是指相邻的或者相关的网站)的脚本。在IT领域,这样的脚本可能用于网络监控、网站...
在Android性能监控中,了解如何使用Python和Shell脚本至关重要,因为它们可以帮助开发者实时获取设备状态,优化应用性能,以及解决可能出现的系统瓶颈。本文将深入探讨如何利用这些脚本工具来监控Android设备的内存...
Python程序设计基础及实践是学习Python编程的关键步骤,尤其对于初学者来说,它提供了一个全面了解这门语言的平台。Python作为一门高级编程语言,以其简洁的语法和强大的功能深受开发者喜爱,广泛应用于Web开发、...
综上所述,"学习Python的学习脚本.zip" 文件可能包含了上述各个方面的实例和练习,通过学习和实践这些脚本,学习者可以逐步掌握Python编程的全面技能。如果文件中的"Kwan1117"是一个子文件夹或具体脚本,那么它可能...
通过阅读和学习这些代码,你可以深入了解如何将OpenCV与网络扫描技术集成,以创建一个实用的监控和安全评估工具。 总结起来,这个项目利用了Python和OpenCV的强大功能,结合了媒体捕获、视频处理与网络扫描,为监控...
这个"Python学习资料整理"压缩包包含了一系列的学习资源,旨在帮助初学者和进阶者提升Python编程技能。 首先,Python的基础知识是理解其语法结构,包括变量、数据类型(如整型、浮点型、字符串、布尔型、列表、元组...
这个教程包含了一个名为"Kwai_download_script-master"的Python脚本项目,以及一份"使用教程.txt",为用户提供清晰的操作步骤。 首先,我们需要理解Python在批量下载中的角色。Python是一种强大的编程语言,其丰富...
MySQL性能监控脚本通常是一段自定义的SQL查询或者自动化脚本,用于收集和分析MySQL服务器的关键性能指标,如查询速度、内存使用、锁等待、表空间占用等。通过定期执行这些脚本,我们可以获取到实时或历史的性能数据...
该标题提及的是一个针对WebLogic的Python脚本,用于检测版本4.18的最新反序列化漏洞。这个脚本,名为`weblogic_poc2628.py`,是漏洞验证工具,它可以帮助安全研究人员或管理员检测其WebLogic服务器是否易受这种特定...
《Python编程:从入门到实践》是一本广受欢迎的Python编程教材,旨在帮助初学者掌握Python语言的基础知识,并通过实际项目提升编程技能。该书涵盖了从基础语法到高级特性的全面教程,同时还提供了丰富的实践项目,使...
在这个场景下,Python脚本可以作为一个强大的工具,帮助我们自动化这些过程,提高效率并减少出错的可能性。 "用于管理和修复Scylla集群的Python脚本"可能包含了若干功能,比如监控Scylla节点的状态、检查数据一致性...
总的来说,"zlg的Python应用"涵盖了从基础的网络通信到复杂的设备控制和数据分析等一系列技术。Python的灵活性和丰富的库资源使其成为这种二次开发的理想选择,开发者可以根据具体需求选择合适的方法和工具,实现...
Shell脚本是Linux中的一个关键概念,它是用bash或其他shell语言编写的可执行文本文件,用于执行一系列命令。学习Shell脚本能帮助你编写自动化任务,如备份、日志分析和系统监控。基础知识点包括变量、条件语句(if-...