需求以及脚本正文
开发人员提出一个需求,想要每天从企业微信号里获取一下阿里云几个RDS的今天和昨天的磁盘容量,对比一下结果来判断删除模块是否正常运行,由于阿里云的相关API不支持查询历史数据,所以我们要建立一个数据表,把磁盘容量按照日期保存在数据表里,这个table的结构如下:
1
2
3
4
5
6
7
8
9#以下是创建databases的语句
CREATE TABLE IF NOT EXISTS `onlinerds`(
`id` INT UNSIGNED AUTO_INCREMENT,
`rds_id` VARCHAR(100) NOT NULL, #记录数据库ID号
`rds_name` VARCHAR(100) NOT NULL, #记录数据库名称
`rds_diskused` VARCHAR(40) NOT NULL, #记录使用磁盘容量
`date` VARCHAR(40) NOT NULL, #记录日期
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
有了这个table,于是就写了一个py3的脚本,内容如下:
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154#!/usr/bin/env python
#coding=utf-8
#这个py3脚本是用来获取阿里云线上数据库的磁盘容量
#pip install pymysql & pip install aliyun-python-sdk-rds & pip install aliyun-python-sdk-core
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.acs_exception.exceptions import ClientException
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdkrds.request.v20140815.DescribeDBInstanceAttributeRequest import DescribeDBInstanceAttributeRequest
import math,pymysql,urllib.request,json,datetime
#字典确定kv对应关系,这样可以取到服务器姓名
dict = {'第一台RDSid': "对应数据库名称",'第2台RDSid': "对应数据库名称",'第3台RDSid': "对应数据库名称",'4台RDSid': "对应数据库名称",'第5台RDSid': "对应数据库名称"}
usedcap=[] #今天磁盘量
usedcap_yes=[] #昨天磁盘量
pro = [] #比例
#创建获取磁盘容量的类
class getRDS(object):
def __init__(self,ak,sk,domain):
self.ak = ak
self.sk = sk
self.domain = domain
client = AcsClient(ak,sk,domain)
#自动换算单位
def convertBytes(self,bytes,lst=None):
if lst is None:
lst = ['Bytes', 'KB', 'MB', 'GB'] # 这里是单位,如果需要TB,PB,在后面添加进去即可
i = int(math.floor( # 舍弃小数点,取小
math.log(bytes, 1024) # 求对数(对数:若 a**b = N 则 b 叫做以 a 为底 N 的对数)
))
if i >= len(lst):
i = len(lst) - 1
return ('%.2f' + " " + lst[i]) % (bytes / math.pow(1024, i))
def DiskUsed(self,rdsid):
lst = ['Bytes', 'KB', 'MB', 'GB']
client = AcsClient(self.ak,self.sk,self.domain)
request = DescribeDBInstanceAttributeRequest()
request.set_accept_format('json')
request.set_DBInstanceId(rdsid)
response = client.do_action_with_exception(request)
result = str(response, encoding='utf-8')
data = json.loads(result)
DiskUsed = ((data)['Items']['DBInstanceAttribute'][0]['DBInstanceDiskUsed']) #获取当前使用磁盘
DiskTotal = ((data)['Items']['DBInstanceAttribute'][0]['DBInstanceStorage']) #获取总磁盘
DiskUsed_GB = getRDS.convertBytes(self,DiskUsed,lst=lst) #使用“自动换算单位”的函数
DiskUsed_num = float(getRDS.convertBytes(self,DiskUsed,lst=lst).split(' ', 1)[0]) #提取纯数字
Proportion = "%.2f%%" % ((DiskUsed_num / DiskTotal) * 100) #转化成百分比
return DiskUsed_GB,Proportion #返回两个值
#获取昨天的日期
def getYesterday():
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
yesterday = today-oneday
return yesterday
#MYSQL录入
def mysql(i,usedcapacity):
db = pymysql.connect("数据库地址", "数据库用户", "密码", "databases",charset='utf8')
cursor = db.cursor()
sql = "INSERT INTO onlinerds (rds_id,rds_name,rds_diskused,date) VALUES ('%s','%s','%s',now())" % (i,dict[i],usedcapacity)
try:
cursor.execute(sql) # 执行sql语句
db.commit() # 执行sql语句
except:
db.rollback() # 发生错误时回滚
db.close() #关闭数据库连接
#获取昨天的数据
def yes_mysql():
db = pymysql.connect("数据库地址", "数据库用户", "密码", "databases",charset='utf8')
cursor = db.cursor()
yes_sql = "select rds_diskused from onlinerds where date like '%s" % (getYesterday()) + " 20:%';"
try:
cursor.execute(yes_sql)
results = cursor.fetchall()
for GB in results:
aaa = GB[0] #增加一个aaa变量来调整格式
usedcap_yes.append(aaa) #获取的数据添加到列表里
except:
print("Error: unable to fecth data")
db.close() #关闭数据库连接
#将类实例化
gethzRDS = getRDS("杭州区ak","杭州区sk","cn-hangzhou")
getszRDS = getRDS("深圳区ak","深圳区sk","cn-shenzhen")
# 获取企业微信token,用来发送微信企业号
def get_token(url, corpid, corpsecret):
token_url = '%s/cgi-bin/gettoken?corpid=%s&corpsecret=%s' % (url, corpid, corpsecret)
token = json.loads(urllib.request.urlopen(token_url).read().decode())['access_token']
return token
# 构建告警信息json,用来发送微信企业号
def messages(msg):
values = {
"touser": '@all',
"msgtype": 'text',
"agentid": 微信企业号应用号码,
"text": {'content': msg},
"safe": 0
}
msges=(bytes(json.dumps(values), 'utf-8'))
return msges
# 发送告警信息,用来发送微信企业号
def send_message(url, token, data):
send_url = '%s/cgi-bin/message/send?access_token=%s' % (url, token)
respone = urllib.request.urlopen(urllib.request.Request(url=send_url, data=data)).read()
x = json.loads(respone.decode())['errcode']
# print(x)
if x == 0:
print('Success!')
else:
print('Failed')
if __name__ == '__main__':
list = ['第一台RDSid','第2台RDSid','第3台RDSid','第4台RDSid','第5台RDSid']
for i in list:
mysql(i,gethzRDS.DiskUsed(i))
x,y = gethzRDS.DiskUsed(i) #函数return多个值,就这样拆开,一一添加到list里
usedcap.append(x) #添加到列表
pro.append(y) #添加到列表
print (i+" OKok!") #证明已经录入到数据库里了
list = ['第一台RDSid','第2台RDSid','第3台RDSid','第4台RDSid','第5台RDSid']
for i in list:
mysql(i,getszRDS.DiskUsed(i))
x, y = getszRDS.DiskUsed(i)
usedcap.append(x)
pro.append(y)
print (i+" OKok!")
yes_mysql()
print(usedcap)
print(usedcap_yes)
corpid = '微信企业号corpid'
corpsecret = '微信企业号应用的秘钥'
url = 'https://qyapi.weixin.qq.com'
msg = '''【第一台数据库】此时的容量是%s,昨天的容量是%s,当前的比例是:%s;
【第2台数据库】此时的容量是%s,昨天的容量是%s,当前的比例是:%s;
【第3台数据库】此时的容量是%s,昨天的容量是%s,当前的比例是:%s;
【第4台数据库】此时此时的容量是%s,昨天的容量是%s,当前的比例是:%s;
【第5台数据库】此时的容量是%s,昨天的容量是%s,当前的比例是:%s;
''' % (usedcap[0],usedcap_yes[0],pro[0],usedcap[1],usedcap_yes[1],pro[1],usedcap[2],usedcap_yes[2],pro[2],usedcap[3],usedcap_yes[3],pro[3],usedcap[4],usedcap_yes[4],pro[4],usedcap[5],usedcap_yes[5],pro[5])
#发送微信告警
test_token = get_token(url, corpid, corpsecret)
msg_data = messages(msg)
send_message(url, test_token, msg_data)
执行之后,效果如下:
小数和百分数的相互转换
百分比转换为小数的代码如下:
1
2
3
4s = '20%' # 默认要转换的百分比是字符串
aa = float(s.strip('%')) # 去掉s 字符串中的 %
bb = aa/100.0 #运行环境是Python2.7 其中Python2.X 与 python 3X中的除法是有区别
print bb # 输出结果是 0.2
小数转换为百分比的代码如下:
1
2
3a = 0.3214323
bb = "%.2f%%" % (a * 100)
print bb # 输出结果是32.14%
如果函数返回了多个值
如果函数一次性return了多个值,如何单独获取到这些值?其实这个函数返回的是一个元组。把元组解包,返回结果也可以赋值给单个变量,这时候这个变量值就是函数返回的那个元组本身了。如下:
1
2
3
4
5
6
7
8def myfun():
return 1, 2, 3
...
a, c = myfun()
a
1
c
3
智能转换存储单位
智能转换bytes
为kb/mb/gb/tb/pb
的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import math
def convertBytes(bytes, lst=None):
if lst is None:
lst=['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
i = int(math.floor( # 舍弃小数点,取小
math.log(bytes, 1024) # 求对数(对数:若 a**b = N 则 b 叫做以 a 为底 N 的对数)
))
if i >= len(lst):
i = len(lst) - 1
return ('%.2f' + " " + lst[i]) % (bytes/math.pow(1024, i))
def main():
lst = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']
bytes = input('Bytes: ')
print convertBytes(bytes, lst=lst)
if __name__ == '__main__':
main()
但是要注意!bytes
作为传入值不能为负数,所以如果是负数想要转换单位,先要用abs
取绝对值再计算。
参考资料
https://www.cnblogs.com/xuchunlin/p/6305720.html
https://python3-cookbook.readthedocs.io/zh_CN/latest/c07/p04_return_multiple_values_from_function.html
https://my.oschina.net/guoenzhou/blog/2989650