dmPython是DM提供的依据Python DB API version 2.0中API使用规定而开发的数据库访问接口。使用API能对DM数据库进行访问。
dmPythonn 接口当前版本号为 2.3,需要对应的DM Server版本为7.0.0.9以上,Python版本为2.6以上。
本次目标任务为获取到服务器与数据库的关键信息后,将结果插入保存数据的数据库中。
IP | 时间 | 内存使用率 | 会话数使用率 |
---|
dmPython路径一般为DM安装路径下的drivers/python/dmPython/目录中。
进入anaconda虚拟环境下执行:
cd /dm/drivers/python/dmPython/
python setup.py install
此时一般会报
Microsoft Visual C++ 14.0 is required
原因是C++包的缺失
此时需要下载Microsoft Visual C++ 14.0的包
提取码:8scp
成功安装后。
输入pip list 会在里面找到dmPython 2.3.0,说明已经安装成功。
dmPython 的运行需要使用 dpi 动态库,用户应将 dpi 所在目录(一般为 DM 安装目录
中的 bin 目录)加入系统环境变量。
这个是时候执行
import dmPython
将会正常输出结果
由于python 3.8为了防止出现DLL 劫持之类的安全风险。限制了DLL的加载规则
必须将DLL包导入到文件的路径才能使用DLL。
import sys
sys.path
输出的结果中找到dmpython-2.3-py3.8-win-amd64.egg
将DM安装路径下的drivers\dpi下所有文件复制到对应的目录下。即可正常打开。
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='192.168.71.50',port='22',username='dmdba',password='123456')
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
print(commandout)
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ip=['192.168.71.50','22','dmdba','123456']
ssh.connect(hostname=ip[0],port=ip[1],username=ip[2],password=ip[3])
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
print(commandout)
现在已经可以监控到我们主机的内存,同理只需要将主机的cpu与磁盘繁忙程度放入监控项。即可完成主机的监控。
可以使用dmPython包进行查询数据库信息与将数据库时间记录。
import dmPython
cursor = dmPython.connect(user='SYSDBA', password='SYSDBA', server='127.0.0.1', port='5236', autoCommit=True).cursor()
cursor.close()#必须加上关闭,否则没执行一次就会多一个无法删除的state为IDLE的会话,当会话数目达到上限值,将无法登录数据库,只能重启实例
构造出了一个cursor,这个时候可以根据cursor进行查询或写入数据库
ACTIVE_SESSIONS_NUM="""
select COUNT(*) from v$sessions where state = 'ACTIVE'
"""
active_sessions_num = cursor.execute(ACTIVE_SESSIONS_NUM).fetchall()#如果之间execute,返回的类型不具有可读性,需要加一个fetchall()转换为list形式。
print(active_seesions_num)
如果想要获取具体的执行SQL信息,可以使用函数SF_GET_SESSION_SQL(),查询结果为TEXT大字段,使用python的cursor.execute 接口,输出结果为str类型。DM目前大字段最大支持长度为2G,如果超过长度就会报错。
现在已经能够获取到当前的内存、活跃会话数。本文目标为获取的是会话数比例。
select
round((session_num/max_num*100.00),2)||'%'
from
(select count(*) as session_num from v$sessions),
(SELECT PARA_VALUE AS max_num FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS')
将sql放入代码中即可得到当前的会话使用率
SESSION_RATE="""
select
round((session_num/max_num*100.00),2)||'%'
from
(select count(*) as session_num from v$sessions),
(SELECT PARA_VALUE AS max_num FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS')"""
session_rate=cursor.execute(SESSION_SQL).fetchall()
print(session_rate)
当数据都能正常获取。需要将数据存放到一个专门的表中进行保存。
这个时候需要插入表。但是如果当表不存在时。执行sql语句将会报错。
由于数据存放库已经不存在,可以选择两种方式
通过人工手动执行脚本。 新建表
获取到不存在表后,自动执行create table命令
本文采用方法为第二种创建一个表。
IP='127.0.0.1'
date=datetime.datetime.now()
try:
DATA_NOW_MONITOR="""
INSERT INTO DATABASE_MONITOR VALUES ('{}','{}' ,'{}','{}');
""".format(IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
data_now_monitor=cursor.execute(DATA_NOW_MONITOR)
print('当前状态为:',IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
except Exception as e:
error_data=(str(e).split(']')[0].replace('[CODE:',''))
if error_data=='-2106':
DATA_CREATE_SHEET="""
create table DATABASE_MONITOR(IP varchar(20),time datetime, mem varchar(10),sess varchar(10));
"""
data_create_sheet=cursor.execute(DATA_CREATE_SHEET)
print('success create table DATABASE_MONITOR')
else:
print(e)
现在已经能够正常的获取和将数据写入数据库中。
将执行的命令写入函数打包,并在主函数中添加循环。
import paramiko
import datetime
import dmPython as dm
import time
def get_database_info(ip,ssh_port,ssh_user,ssh_passwd,database_port,database_user,database_passwd):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
cursor = dm.connect(user=database_user, password=database_passwd, server=ip, port=database_port, autoCommit=True).cursor()
ssh.connect(hostname=ip,port=ssh_port,username=ssh_user,password=ssh_passwd)
commandin,commandout,commanderr=ssh.exec_command('free')
commandout=commandout.read().decode('utf-8')
ssh.close()
date=datetime.datetime.now()
try:
DATA_NOW_MONITOR="""
INSERT INTO DATABASE_MONITOR VALUES ('{}','{}' ,'{}','{}');
""".format(IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
data_now_monitor=cursor.execute(DATA_NOW_MONITOR)
print('当前状态为:',IP,date,str(round(int(commandout.split()[8])/int(commandout.split()[7])*100.0,2))+'%' ,session_rate[0][0])
except Exception as e:
error_data=(str(e).split(']')[0].replace('[CODE:',''))
if error_data=='-2106':
DATA_CREATE_SHEET="""
create table DATABASE_MONITOR(IP varchar(20),time datetime, mem varchar(10),sess varchar(10));
"""
data_create_sheet=cursor.execute(DATA_CREATE_SHEET)
print('success create table DATABASE_MONITOR')
else:
print(e)
if __name__ == '__main__':
while(1):
conf=['192.168.71.50','22','dmdba','123456','5236','SYSDBA','SYSDBA']#可以直接写conf,也可以将conf写成一个conf配置文件,方便拓展
# with open('conf.txt',encoding='utf-8') as log_file:
# for files in log_file:
# files=files.replace('\n','')
# if files != '':
# conf.append(files)
for i in range(0,len(conf)-1,7):
get_database_info(conf[i],conf[i+1],conf[i+2],conf[i+3],conf[i+4],conf[i+5],conf[i+6])
time.sleep(10)#10s查询一次