教研室有台tplink不知道怎么回事,总是自己掉线,还是很奇葩的那种掉线,明明ip和网关都变0.0.0.0了,还是显示在线,导致自带的自动登陆功能不起作用。
之前都是手动check和重新登陆,实在是浪费生命,于是乎来个定时脚本搞定吧,反正教研室有24小时online的服务器。
整个任务大体上分为三个步骤:
- 分析tplink管理API
- 编写管理脚本
- 使用systemd timer定时启动脚本(当然cron也是可以的,但是作为Archer,怎么能不用最新技术~)
1. 分析tplink管理API
首先登陆http://192.168.0.1 (替换成自己的管理地址,下同)
,教研室的这个型号是WR842N,登陆界面及其简单,就一个密码框。一开始我以为是把密码用明文或者hash一下post给路由,但是填写密码后发现没有post数据,百思不得其解,后来几番搜索,找到一篇分析的好文,这篇文章不仅告诉了如何登陆,而且还分析的很详细。想了解详情的请参见这篇blog。至于代码,我做了简化,直接把chrome里监控到的header粘进代码发送,简单粗暴~
2. 编写管理脚本
重点来了,先贴代码:
#!/bin/python3 # -*- coding: utf-8 -*- import urllib.request import sys progArgs = ["get_status", "login"] ip = "192.168.0.1" headers = { "Host": "192.168.0.1", "Connection": "keep-alive", "Pragma": "no-cache", "Cache-Control": "no-cache", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/65.0.3325.181 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Referer": "http://192.168.0.1/userRpm/StatusRpm.htm", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,bg;q=0.6,la;q=0.5", "Cookie": "Authorization=*你的authorization值*" } statusUrl = "http://" + ip + "/userRpm/StatusRpm.htm" loginUrl = "http://" + ip + "/userRpm/WanCfgRpm_8021X.htm" \ "?wantype=3" \ "&Ieee802_1xName=*你的宽带账户*" \ "&Ieee802_1xPwd=Hello123World" \ "&dialMode=2" \ "&Login=%B5%C7+%C2%BC&IpType=1" \ "&sta_ip=" \ "&sta_mask=" \ "&sta_gateway=" \ "&mtu=1500" \ "&ieeeType=3" #logoutUrl = "http://" + ip + "/userRpm/StatusRpm.htm?Logout=%CD%CB%20%B3%F6&wan=1" logoutUrl = "http://" + ip + "/userRpm/WanCfgRpm_8021X.htm" \ "?wantype=3" \ "&Ieee802_1xName=*你的宽带账户*" \ "&Ieee802_1xPwd=Hello123World" \ "&Logout=%CD%CB+%B3%F6" \ "&IpType=1" \ "&sta_ip=" \ "&sta_mask=" \ "&sta_gateway=" \ "&mtu=1500" \ "&ieeeType=3" \ "&IeeeReqFlag=0" def get_url(url_arg): if url_arg == "get_status": req = urllib.request.Request(statusUrl, None, headers) elif url_arg == "login": //先登出,再登入,防止特殊情况 req = urllib.request.Request(logoutUrl, None, headers) req = urllib.request.Request(loginUrl, None, headers) else: # default, should never reach here req = urllib.request.Request(statusUrl, None, headers) resp = urllib.request.urlopen(req) print(resp.read()) def print_help(): base_help_str = "Usage: " + sys.argv[0] + " " print(base_help_str + "|".join(progArgs)) if __name__ == "__main__": if len(sys.argv) != 2 or sys.argv[1] not in progArgs: print_help() exit(1) else: get_url(sys.argv[1])
代码很简单,主要是注意发送get的地址,这个用chrome的开发者工具点击相应的管理按钮监控network栏很容易get。需要注意的地方有三个,一个是ip
,这个填写你的路由管理ip,一个是header
,这个打开chrome开发者控制台,输入密码登陆的时候,看network栏的发送header,粘进代码即可,还有一个是statusUrl
和loginUrl
,这些都可以用控制台监控到,而且也是基本操作,不再赘述。
3. 使用systemd timer定时启动脚本
程序是写好了,该定时运行了。这里我使用的是systemd timer,写起来也很简单。首先写个shell script判断路由器是不是真的掉线了,直接上代码:
#!/bin/env bash count=`/usr/bin/python3 /home/hp/scripts/tplink_helper.py get_status|grep -o 0.0.0.0|wc -l` if [ $count -gt 5 ]; then /usr/bin/python3 /home/hp/scripts/tplink_helper.py login fi
代码依然很简单,通过python脚本获得response之后,grep -o 0.0.0.0
获得0.0.0.0
的个数,这个在正常情况下我获得的数量是5个,因此只要大于5个肯定是异常了,就应该执行登陆命令。
接下来写一个systemd service和systemd timer文件放到/etc/systemd/system
,当然规范的方式是放到用户的systemd配置文件夹下,因为整个脚本不需要root权限。但是这台服务器不止一个人用,这种涉及管理其他硬件的脚本应该统一放在一起更好管理。
tplink_monitor.service
的代码:
[Unit] Description=Monitor the tplink router [Service] Type=simple ExecStart=/bin/bash /home/hp/scripts/tplink_monitor.sh >/dev/null 2>&1
tplink_monitor.timer
的代码:
[Unit] Description=Monitor the tplink every 5 min [Timer] # Time to wait after booting before we run first time OnBootSec=10min # Time between running each consecutive time OnUnitActiveSec=5min Unit=tplink_monitor.service [Install] WantedBy=multi-user.target
内容很简单,不熟悉systemd配置文件语法也可以很轻松看懂。
接下来就是start脚本和enable脚本,保证开机自动运行
# systemctl start tplink_monitor.timer # systemctl enable tplink_monitor.timer
接下来就是测试,测试的时候可以把OnUnitActiveSec=5min
时间改的小一点。
代码github地址:https://github.com/callofdutyops/tplink_monitor
Permalink
呵~~~systemd的拥趸