动机与脚本
我工位所用的网络是公司特批的海外专线,速度OK还能翻墙出去看看,自从有了这条线爽的飞起,但缺陷就是每周IP地址都会变,IP一变很多的阿里云ecs安全组就要重新配置,因为有一些公网端口比如grafana或者跳板机是只能公司运维人员访问的。这样每周都要手动改一次IP地址太烦了,于是乎,写了下面这个脚本,一劳永逸的解决这个问题:
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#coding=utf-8
#这个脚本在python3.6下自验通过,用途是去爬当前的IP地址然后给阿里云安全组添加新的IP,并且删除掉老的IP
from aliyunsdkcore import client
from aliyunsdkecs.request.v20140526 import AuthorizeSecurityGroupRequest
from aliyunsdkecs.request.v20140526 import RevokeSecurityGroupRequest
from aliyunsdkcore.profile import region_provider
import requests,sys,re,os
from bs4 import BeautifulSoup
clt = client.AcsClient('这里是AK', '这里是SK', 'cn-hangzhou') #鉴权
file = "F:\\ip.txt"
def checkDIR():
global file
if os.path.exists(file) == True: #先判断文件是否存在
with open(file, "r") as f:
old_ip = f.read()
return (old_ip) #获取旧ip
else:
print("ip.txt文件不存在,请手动生成!")
sys.exit() #文件不存在直接退出
def getIP():
global file
r = requests.get('http://www.ip111.cn/') #这里输入要爬的网站域名
soup = BeautifulSoup(r.text, "lxml")
context = []
for link in soup.find_all('td'): #获取所有td标签内容
context.append(link.get_text()) #添加一个列里
str = context[4]
ip = re.split(r'[\n\s]\s*', str)[1] #多符号分割字符串
with open(file, "w") as f:
f.write(ip)
return ip
def addnewRULE(func):
global clt
# 设置参数
for port in ['3000/3000', '34872/34872']: #这里是端口
request = AuthorizeSecurityGroupRequest.AuthorizeSecurityGroupRequest()
request.set_accept_format('json')
request.add_query_param('RegionId', 'cn-hangzhou')
request.add_query_param('SecurityGroupId', '目标安全组ID')
request.add_query_param('IpProtocol', 'tcp')
request.add_query_param('PortRange', port)
request.add_query_param('SourceCidrIp',func())
request.add_query_param('NicType', 'intranet') #如果不加这句话就是公网添加
if port == '3000/3000':
request.add_query_param('Description', 'Grafana使用端口')
else:
request.add_query_param('Description', 'Zabbix和堡垒机使用端口')
# 发起请求
response = clt.do_action(request)
print (response)
def deloldRULE(func):
global clt
# 设置参数
for port in ['3000/3000','34872/34872']:
request = RevokeSecurityGroupRequest.RevokeSecurityGroupRequest()
request.set_accept_format('json')
request.add_query_param('RegionId', 'cn-hangzhou')
request.add_query_param('SecurityGroupId', '目标安全组ID')
request.add_query_param('IpProtocol', 'tcp')
request.add_query_param('PortRange', port)
request.add_query_param('SourceCidrIp', func())
request.add_query_param('NicType', 'intranet') #如果不加这句话就是公网删除
# 发起请求
response = clt.do_action(request)
print (response)
if __name__ == '__main__':
checkDIR()
deloldRULE(checkDIR)
getIP()
addnewRULE(getIP)
整个脚本的逻辑就是先在F盘下有ip.txt
里面就保存当前IP地址,然后执行脚本的时候就会先在目标安全组里删除掉这个IP相关的3000端口和34872端口,然后去www.ip111.cn
里爬取当前的网址,把新IP写入到ip.txt
的同时,再去目标安全组里添加这个新IP相关的3000端口和34872端口。
新的知识点
- 把上一个函数结果当作参数在下一个函数里执行的方法:
python的退出有两个:
os._exit()
和sys.exit()
:os._exit()
会直接将python程序终止,之后的所有代码都不会执行;sys.exit()
会抛出一个异常:SystemExit
,如果这个异常没有被捕获,那么python解释器将会退出。如果有捕获该异常的代码,那么这些代码还是会执行。使用sys.exit()
来退出程序比较优雅,一般情况下也用这个,os._exit()
可以在os.fork()
产生的子进程里使用。在windows里定时执行python脚本的方法:
打开控制面板
—>系统和安全
—>计划任务。
如图:
点击右侧的创建基本任务
,输入任务名称和可选的描述。点击下一步
,设置任务的开始时间,可以选择每日执行、每周执行或每月执行。点击下一步
,操作
选择启动程序
,点击下一步输入参数。如图:
1
2
3程序或脚本:python.exe
添加参数:输入要执行的python脚本路径(包括文件名)
起始于:输入python.exe的目录(不包括文件名)
最后点击下一步
,整个过程搞定。
- 目前
http://www.ip111.cn/
网站已经更改了网页格式,上述的代码有一段已经不好使了,需要将getIP()
这个函数改成如下的方法:1
2
3
4
5
6
7
8
9
10
11
12def getIP():
global file
r = requests.get('http://2018.ip138.com/ic.asp') #改用这个域名
soup = BeautifulSoup(r.text, "lxml")
context = []
for link in soup.find_all('body'): #获取body内容
context.append(link.get_text()) #添加一个列里
str = context[0]
ip = re.split(r'[\[\]]',str)[1] #进行分割
with open(file, "w") as f:
f.write(ip)
return ip