美文网首页Python七号
我用 Python 造了个运维小小弟

我用 Python 造了个运维小小弟

作者: somenzz | 来源:发表于2018-08-21 06:36 被阅读146次

    阅读本文大约需要 3 分 50 秒。

    周六,正和家人在外边玩得起劲,突然接收到微信报警,某某系统供数出错......

    此时,内心是崩溃的,有一万个草泥马在翻腾,我能瞬间说出这系统的 100 个缺陷。

    然而,也有另外一个声音在耳边提醒着:报怨是最没用的,可怜之人必有可恨之处,老板在乎不是你的苦劳,而是你的功劳。

    算了,回家打开电脑,解决报错。

    以上的场景做过运维的朋友想必比较熟悉,没做过运维的人相信也有类似的经历,总之就是那些让你不爽的事,如果这些不爽的事与电脑有关,不妨继续一看。

    痛定思痛,我再也不愿意做如此重复又没技术含量的杂事了,今天必须拿出一个方案来。

    1. 向领导说不干这个了
    2. 换系统
    3. 自己想办法解决

    俗话说三思而后行,常言道换位思考,当今互联网时代更要学会产品思维。
    假如我是客户,我会喜欢什么样的产品呢?肯定是有问题会自我修复的产品,如果确实无法自我修复,应该提示我升级或找售后维护,如果拒绝服务却又没有任何信息提示,那么这个产品只好废弃不用了。作为一名员工,其实也是领导的一款产品,需要提高自己的核心竞争力,做别人不愿做或做别人做不好的事,这样才能体现自己的价值。这样想,心情平静了许多。

    那么,我选择先做 3 。

    分析问题:这个属于系统 bug,上传失败通过在网页上再点一次上传按钮就可以传成功。

    不如干脆造个运维小小弟在报错的时候自动帮我点下得了!想到这里,我被自己想法折服了,这个还真可以实现,找当今稳排第一的编程语言 Python 来实现这个小小弟就成了,毕竟还是打过交道的,应该没有大问题。

    撸起袖子开始工作。

    思路:我需要的是一个可以在网页上自动操作的小小弟,因此先分析网页 Web 请求,再选取相应的工具,最后编码调试。

    第一步 分析网页。网站是需要登陆的,打开 Chrome 浏览器,输入用户名和密码,按 F12 /或 Ctrl + Shift + I 打开开发者工具 ,勾选以下选项。

    Chrome 开发者工具

    再点击登陆按钮,然后查看开发者工具的网络请求记录。

    登陆请求

    发现这一步为 POST 请求,参数中出现了刚才输入用户名密码,这里未加密,有些网站密码可能通过JavaScript 对密码进行了加密后上传至服务器的,此时则需要使用加密后的密码提交 Post 请求。查看其 ResPonse 如下:

    登陆请求的返回结果

    发现返回值是 Json 格式的字符串,有个 methodName 为 login,参数也是刚才输入的用户名密码,更进一步说明,这一请求就是验证登陆用户是否合法的。

    第二步 选取工具。这里涉及到爬虫,我熟悉的爬虫工具有 urllib(标准库),requests(第三方库),selenium(第三方库),
    urllib 比较简单,实现 Session 有点麻烦;selenium 太笨重,虽然可以运行 JavaScript,但是需要浏览器驱动,找各种元素的 xpath,运行起来也很慢;而 requests 库就非常 Pythonnic ,简单而优雅,能轻松处理 Session ,这也是我的最爱用的工具。
    于是选定 requests 先做一个登陆验证。

    第三步 编码调试。由于页面需要登陆,因此需要保留与服务器通讯的会话 Session。
    登陆的代码如下:

    import requests
    s = requests.Session()
    url = "http://xxx.xxx.xxx.xxx:9080/******/vision/RMIServlet"
    data = {
        "className": "UserService",
        "methodName": "login",
        "params": '["admin","******"]',
    }
    r = s.post(url, data=data)
    print(r.text)
    print(r.status_code)
    

    执行结果为

    {"retCode":0,"result":true}
    200
    

    返回 200 说明访问成功,小兴奋了一把。接着,同样的方法我点击供数配置菜单,得到供数的页面,继续分析。

    供数配置与监控.png 供数配置与监控-返回页面参数.png

    第二步的点击供数配置菜单对应的代码如下:

    import requests
    import json
    s = requests.Session()
    url = "http://xxx.xxx.xxx.xxx:9080/******/vision/RMIServlet"
    data = {
    "className": "UserService",
    "methodName": "login",
    "params": '["admin","******"]',
    }
    r = s.post(url, data=data)
    print(r.text)
    print(r.status_code)
    
    data2 = {
       "className": "UrlLinkService",
       "methodName": "getURLLink",
       "params": '["I8ae3cd903146dcb1013146df075c000c"]',
    }
    r2 = s.post(url, data=data2)
    print("获取供数配置页面参数信息",r2.status_code)
    result = json.loads(r2.text) # 将Json 字符串转化为 Python 字典
    print(result['result']['url']) # 获取 url 参数
    

    运行结果如下:

    {"retCode":0,"result":true}
    200
    获取供数配置页面参数信息 200
    /bioffice/vision/SupplyManagement?opFlg=querySysCfgTask&forwardPage=list.jsp
    

    接下来,点击我们要处理的系统名称,再点击详细信息,找到重新上传按钮,注意每一步的 Post 或 Get 请求,道理都是通的,编写相应的 Post 或 Get 代码即可。
    完整代码如下所示:

    import requests
    import json
    s = requests.Session()
    url = "http://xxx.xxx.xxx.xxx:9080/******/vision/RMIServlet"
    data = {
    "className": "UserService",
    "methodName": "login",
    "params": '["admin","******"]',
    }
    r = s.post(url, data=data)
    print(r.text)
    print(r.status_code)
    
    data2 = {
    "className": "UrlLinkService",
    "methodName": "getURLLink",
    "params": '["I8ae3cd903146dcb1013146df075c000c"]',
    }
    r2 = s.post(url, data=data2)
    print("获取供数配置页面参数信息",r2.status_code)
    result = json.loads(r2.text) # 将Json 字符串转化为 Python 字典
    print(result['result']['url']) # 获取 url 参数
    
    
    url3 = f"http://xxx.xxx.xxx.xxx:9080{result['result']['url']}"
    #print(url3)
    r3 = s.get(url3)
    print(r3.url, r3.status_code)
    
    taskinfo = ['988909',CRM.DJJGXCKMX','2018-08-19','CRM'] #实际使用时可做为参数传入
    
    payload0 = {
        "opFlg": "queryTask",
        "forwardPage": "listtask.jsp",
        "sysid": taskinfo[3],
        "sysname": "",
        "rundate": taskinfo[2],
    }
    payload1 = {
        "opFlg": "modifyTask",
        "forwardPage": "listtask.jsp",
        "flg": "U",
        "sid": taskinfo[0],
        "vname": taskinfo[1],
        "rundate": taskinfo[2],
    }
    
    r4 = s.get(
        "http://xxx.xxx.xxx.xxx:9080/******/vision/SupplyManagement", params=payload0
    )
    r5 = s.get(
        "http://xxx.xxx.xxx.xxx:9080/******/vision/SupplyManagement", params=payload1
    )
    
    print(r4.url, r4.status_code)
    print(r5.url, r5.status_code)
    if r5.status_code == 200:
        print("已执行上传")
    else:
        print("执行上传失败")
    

    测试环境验证:
    执行前:


    测试0.png

    原本运行结束时间为 2018-08-20 05:37:11
    执行上述代码,打印信息如下:

    {"retCode":0,"result":true}
    200
    获取供数配置页面参数信息 200
    /bioffice/vision/SupplyManagement?opFlg=querySysCfgTask&forwardPage=list.jsp
    http://xxx.xxx.xxx.xxx:9080/******/vision/SupplyManagement/list.jsp 200
    http://xxx.xxx.xxx.xxx:9080/******/vision/SupplyManagement/listtask.jsp 200
    http://xxx.xxx.xxx.xxx:9080/******/vision/SupplyManagement/listtask.jsp 200
    已执行上传
    

    再次查看运行结束时间为2018-08-20 22:47:39

    测试1.png

    说明这个小小弟已经成功的为我执行了重新上传的任务,后续可监控的报警信息传递给这个小小弟,小小弟就可以在生产环境自动帮我处理上传失败的问题了。

    总结:只要思想不滑坡,办法总比困难多。上面分享的这些,对于懂 http 协议的人来说简单地就像老戏骨看小娃娃表演一般,所以起名叫小小弟,他的功能还是非常简单的,但是把这些技术用于解决实际的运维问题我认为还是比较有意义的,具有自动修复功能的运维才是真正的自动化运维。后续会逐步加强小小弟的功能。

    END

    公众号搜 somenzz 关注我。

    相关文章

      网友评论

        本文标题:我用 Python 造了个运维小小弟

        本文链接:https://www.haomeiwen.com/subject/pofriftx.html