上周一,也就是2020年12月14日,美国老牌NMS公司Solarwinds宣布该公司遭受了来自某国(据称是俄罗斯)黑客国家队的攻击,其著名的NMS软件Solarwinds Orion在最新一期的补丁更新中被植入了后门程序,所有使用Solarwinds Orion并打了最新补丁的公司都会中招。有报道称,该攻击相信在今年3月份就已经开始,只是一直没被发现,并且黑客团队为此已经预谋了数年之久。Solarwinds宣布自己旗下18000多个客户应该都受到了影响,因为一般来说所有公司的内网防火墙和网络安全设备一般是对所有来自网络监控系统的流量全部放行,不做任何检查的(我猜想这也是为什么俄罗斯黑客会瞄准知名NMS软件来攻击)。

不幸的是,我所在的沙特阿卜杜拉国王科技大学(KAUST)使用的NMS正是Orion,管理层当天即下令彻底关闭Solarwinds Orion,等待Solarwinds放出解决该攻击的更新补丁后才继续使用Orion。关闭Orion后,由我带头用Python写了监控全校上万台网络设备的脚本,并给同事们上了Python培训课,在培训时有同事问我怎样才能让主机定时或每隔几分钟来自动执行Python脚本来监控网络。

一般来说,遇到诸如此类让主机定时或每隔多长时间自动执行脚本的需求时,我们最先想到的是通过Windows的Task scheduler或者Linux的Crontab来实现,但是这需要网工本身具备一定的Windows和Linux服务器的运维知识,虽然这类知识本身上手难度不高,但是很大一部分网工所在的公司并不见得有专门的运维服务器,即使有一般也是有专门的系统工程师负责维护,网工没那个权限去管理。其实除了Task Scheduler和Crontab之外,Python本身还有一个很好用的第三方模块schedule也能实现这个需求,并且schedule模块的句法非常易读(英语具备小学水平即可),是我见过最通俗易懂,上手最容易,功能又十分强大的Python模块之一,这篇文章就来介绍下schedule的用法。


安装schedule模块

通过pip install schedule即能安装schedule,非常简单,这里就不演示了。

Schedule模块基本用法

Schedule模块的句法非常易懂,基本把它当成一句简单的英语来读就行了,schedule模块有schedule.every(), schedule.run_pending(), schedule.run_all(), schedule.idle_seconds(), schedule.next_run(), schedule_cancel_job()等六类函数,其中对我们来说最常用的是schedule.every()和schedule.run_pending()函数,它们的用法如下:

schedule.every(interval=1).(seconds,minutes,hours,days).do(task)

表示每隔多少(秒,分钟,小时,天),默认间隔是1,也就是每隔(一秒、一分钟、一小时、一天)要做什么任务(所谓的任务通常是指一段含有数行代码的自定义函数)。

schedule.run_pending():

所有被排入schedule中的任务都不会马上被执行,而是进入pending状态,而schedule.run_pending()这个函数的作用就是立即执行所有状态为pending的函数。

下面来看个例子:

#test.py import schedule from datetime import datetime def job(): now = datetime.now() time = now.strftime("%H:%M:%S") print (f'现在的时间是: {time}') schedule.every(3).seconds.do(job) while True: schedule.run_pending()

代码讲解:

import schedule from datetime import datetime

def job(): now = datetime.now() time = now.strftime("%H:%M:%S") print(f'现在的时间是: {time}')

schedule.every(3).seconds.do(job)

while True: schedule.run_pending()

执行脚本看效果:

python设计方案(网络工程师的Python之路)(1)

可以看到每隔三秒钟schedule模块便帮助我们自动运行了一次job()函数,因为while True的存在。只要不使用Ctrl C停止脚本,或者重启运行脚本的主机的话,该脚本将一直运行下去,也就实现了我们“挂机”的目的。

下面再举一个例子,我们使用schedule模块来实现让Python脚本每隔3分钟自动ping一次http://www.cisco.com以检测外网可达性的目的:

#test.py from pythonping import ping import schedule host = 'www.cisco.com' def ping_test(): ping_result = ping(host) if 'Reply' in str(ping_result): print (host '可达。') else: print (host '不可达。') schedule.every(3).minutes.do(ping_test) while True: schedule.run_pending()

运行脚本看效果:

python设计方案(网络工程师的Python之路)(2)

这里我们使用schedule并配合pythonping模块来让Python每隔3分钟自动ping http://www.cisco.com,关于pythonping模块的用法在我书里有讲过,这里就不赘述了,只需要注意使用pythonping的时候必须使用root(Linux)或者管理员帐户(Windows),否则会出现权限不够的异常。最后我们用Ctrl C终止程序(末尾的KeyboardInterrupt即为Ctrl C后的Python抛出的异常,这是正常的,不要惊慌,如果你不喜欢看红色的字体的话,可以自己写个try/except来做异常处理。)

除了每隔多长时间做任务外,我们还可以通过schedule设置在固定什么时候做什么任务,举例如下:

#test.py import schedule def job(): print (‘每个星期五的早上5点做一次任务。') schedule.every().friday.at("05:00").do(job) while True: schedule.run_pending()

这里代码就不讲解和演示了,schedule.every().friday.at("05:00").do(job)这句代码你直接把它当成一句英语句子读也该知道什么意思,要是想表达每周二做什么,就把friday换成tuesday,要是想表达每天做什么,就把friday换成day即可,要是想表达每天下午5点做什么,就把05:00换成17:00即可,够简单吧?

学会了schedule模块后,作为网工的我们可以做很多事情,比如固定在每天凌晨1点自动备份一次所有网络设备的配置,每隔半个小时查看一次CPU的用量,每隔几分钟ping一次某设备以达到监测的目的,等等等等,具体就看各位自己的需求了。

,