最近发现有几台ftp服务器非常不稳定,造成 服务不可用,最要命的是都是用户报上来的,这种事完全违背咱们运维高大上自动化监控水准,经查发现之前管理员没加ftp应用监控,NND,原来一直在无政府状态下工作呀,现在到我手里,就不能任由你们了,做运维的都知道,不怕有问题,就怕你发现不了或者出现了问题,好几天才知道,当然如果boss比你先知道,你就只能呵呵了,所以呢,本着对工作负责的态度,今天咱们就要给所有ftp服务器个监控,基本思路是检查ftp服务的可用性,发现有问题就通知管理员,因为需求比较简单,都自己写了个python脚本实现了,前戏如下:
1、在每台ftp服务器上创建一个ftp用户用来检查ftp登录测试。
2、提供一个配置文件,可以由用户自己配置要检查的服务器列表。
3、然后程序根据提供的用户名称和密码登录每台ftp测试是否成功,判断成功或失败,然后将反馈的状体写入status.txt文件中。
4、因为ftp服务器比较多,所以脚本采用的线程方式运行。
全部代码如下,稍后解释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#encoding=utf-8 #__author__ = 'glacier' #date:20151025 import os.path import ConfigParser from ftplib import FTP_TLS from threading import Thread import socket import ssl cf = ConfigParser.ConfigParser() cf.read(r'e:\project1\ftplist.txt') user = 'check_login' password = '45H' server_info = [] #定义FTP_TLS类 class IMPLICIT_FTP_TLS(FTP_TLS): def __init__(self, host='', user='', passwd='', acct='', keyfile=None, certfile=None, timeout=60): FTP_TLS.__init__(self, host, user, passwd, acct, keyfile, certfile, timeout) def connect(self, host='', port=0, timeout=-1): if host != '': self.host = host if port > 0: self.port = port if timeout != -1: self.timeout = timeout try: self.sock = socket.create_connection((self.host, self.port), self.timeout) #self.af = self.sock.family self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) self.file = self.sock.makefile('rb') self.welcome = self.file.readline() except Exception as e: print e return self.welcome #获得配置文件信息,转换成列表 def get_ip_port(): for arg in cf.sections(): ip, port = cf.options(arg) ip = cf.get(arg, ip) port = cf.get(arg, port) info = (ip, port) server_info.append(info) return server_info #检查函数,测试是否ftp登录ok def check_login(ftp_server, ftp_port): try: ftps = IMPLICIT_FTP_TLS() #print help(ftps) ftps.connect(host=ftp_server, port=ftp_port) ftps.login(user=user, passwd=password) ftps.quit() return 1 except: return 0 #根据检查的成功或失败,写入文件 def write_status(ftp_server, ftp_port): result = check_login(ftp_server, ftp_port) f = open(r'e:\project1\status.txt', 'a+') if result == 1: f.write(ftp_server + ' login ok' + '\n') else: f.write(ftp_server + ' login error' + '\n') f.close() #主函数,判断文件大小是否为0,非0重置文件,保持文件内容最新,多线程检查。 if __name__ == '__main__': threads = [] server_info = get_ip_port() if os.path.getsize(r'e:\project1\status.txt'): f = open(r'e:\project1\status.txt', 'r+') f.truncate() f.close() for i in range(0, len(cf.sections())): ip, port = server_info[i] threads.append(Thread(target=write_status, args=(ip, port))) for thread in threads: thread.start() for thread in threads: thread.join() |
开始先定义了一个类,用来做加密传输,前面已经说了,我的ftp都是加密传输的,所以要ssl socket 进行封装建立一条加密的socket,get_ip_port()函数是从配置文件中获取要检查的ftp server信息,返回一个列表,check_login()函数是进行模拟登录的函数,如何成返回1,否则返回0,write_status()函数是根据check_login()函数返回的结果,将状态信息写入状态文件中。
因为每次都要获取最新的状态内容,所以每次程序检查前要判断status.txt文件是否有内容,如果有要就删除,写入最新的状态检查内容,os.path.getsize()函数是判断文件是否为0,如果不为0,就是返回真值,就打开文件,f.truncat()清空文件内容,然后进入线程执行部分,开始一个for循环是根据配置文件中返回的sections长度作为循环的条件,然后把每个线程加入一个线程列表,然后循环线程列表,开始thread.start(),最后一个for循环是等待线程结束thread.join(),即主线程不退出等待所有线程结束后退出,写到这基本的程序就介绍完了,接下来要说如何部署了。
部署:
1、编辑crontab ,每三十分钟检查一次。
*/30 * * * * python /root/scripts/check_ftp_status.py
2、写一个脚本,检查生成的status.txt文件是否有有error,如果有发邮件给管理员,因为这个脚本很简单,我就不贴了,我相信懂点shell脚本的兄弟肯定没问题,如果真有问题,可以留言给我,我发你,还有这个脚本也是要放入crontab中的,因为要定时检查。
写在最后:
因为我的ftp是加密传输的,所以会稍微复杂一些,因为要封装一个加密的socket,要先定义一个类,如果不是加密传输的ftp,会更简单,直接调用 FTP这个模块类就可以了,具体内容可以看官方文档。
另外这种监控方式还是比较low,因为急用,所以就先上了,当然比较好点的是写一个程序来读取生成的文件内容,展示到web上,定时刷新一下,就可以看到最新的状态结果了,这个程序后续有精力我就会写,当然博客就不更新了,代码会放入github上,需要的朋友可以关注,查看更新。
最后说明,因为我是在windows下编写的,所以测试都是用的windows目录,如果哪位兄弟用在linux下,可以自行修改目录和配置文件地址。