【环境介绍】
系统环境:Linux + Python 2.7.10(监控主机)
【背景描述】
需求:每次节假日或者重要时间时,需要对数据库主机信息进行检查,比如主机空间使用率之类。有时候需要执行数据库特有的命令查询信息,比如查询数据库补丁信息。但是由于主机较多需要每次登录主机进行查询,需要的时间较长。为提高批量查询或者执行命令来查询主机命令层面上的信息,需要用脚本来提高效率。
【监控优化过程及思路】
对于上面描述的问题:
- 基于执行命令需要批量登录主机,对于安全性考虑决定用Python来进行批量登录主机,需要Crypto和paramiko模块模块
Paramiko,Crypto模块遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接。
安装pycrypto模块前提需要安装GCC依赖包:
yum -y install gcc
wget http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.6.tar.gz
tar -xf pycrypto-2.6.tar.gz
cd pycrypto-2.6/
python setup.py build && python setup.py install
安装paramiko模块安装报错需要安装setuptools模块:
wget https://pypi.python.org/packages/2b/27/b64860e7b208ff1dd36fe208d07bca1f9637a11fe733e2f2ceea587c3f75/paramiko-1.7.5.zip
unzip paramiko-1.7.5.zip
cd paramiko-1.7.5
python setup.py build && python setup.py install
Traceback (most recent call last):
File "setup.py", line 6, in <module>
from setuptools import setup, find_packages
ImportError: No module named setuptools
安装setuptools模块:
https://pypi.python.org/pypi/setuptools
unzip setuptools-38.5.1.zip
cd setuptools-38.5.1
python setup.py build && python setup.py install
测试Paramiko和Crypto模块是否正常调用:
[oracle@mysqldb1 python2.7.10]$ python
Python 2.7.10 (default, Nov 29 2017, 20:27:52)
[GCC 4.8.2 20140120 (Red Hat 4.8.2-16)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Crypto
>>> import paramiko
>>>
- 主机采集信息,自带命名不需要设置,调用其他用户命令需要设置环境变量,将需要执行的命令直接加入profile配置文件中即可。
设置变量:
PATH=/home/oracle/opt/python2.7.10/bin:$ORACLE_HOME/jdk/bin:$ORACLE_HOME/OPatch:$PATH
export PATH
【测试结果及脚本】
通过测试脚本。结果如下:
- 主机数据信息:截图如下:
实现交互式执行主机命令,输入命令后直接回车即可。可以是任何主机可执行命令。
- 数据库信息:截图如下:
预先加载用户的profile文件配置后执行命令:
source ~/.bash_profile;~/.profile;opatch version
【采集数据脚本信息】
主要实现功能的脚本如下:
[oracle@mysqldb1 python]$ cat ssh_hosts.sh
######################################################################
# ssh_hosts.sh
# This script is check host data
# Author CZT
######################################################################
#!/bin/bash
cat .liebiao.txt |awk '{print $5}'|grep -v 'HOSTIP'> tmp_ipadress.txt》》》加载IP信息
cat .liebiao.txt |awk '{print $4}'|grep -v 'PASSWORD'> tmp_password.txt》》》加载密码信息
python ssh_hosts.py》》》调用Python脚本批量登录主机执行命令
[oracle@mysqldb1 python]$ cat .liebiao.txt
######################################################################
# liebiao.txt
# This script is hosts data
# Author CZT
######################################################################
TYPE DBNAME USERNAME PASSWORD HOSTIP
XXM XXDB1 oracle oracle 192.168.142.140
XXM XXDB1 oracle oracle 192.168.142.140
XXM XXDB1 oracle oracle 192.168.142.140
XXM XXDB2 oracle oracle 192.168.142.140
》》》安全考虑可以使用临时写入列表信息文件,主机信息可自己添加即可,IP为测试IP信息
[oracle@mysqldb1 python]$ cat ssh_hosts.py
######################################################################
# ssh_hosts.py
# This script is check hosts command
# Author CZT
######################################################################
import paramiko》》》加载paramiko模块
# Define the ipaddress array.》》》加载主机IP信息为数组
patch_file_name1="tmp_ipadress.txt"
inFile1= open(patch_file_name1,'r')
ipadress = []
for line1 in open(patch_file_name1):
trainingSet = line1.split('\n')
ipadress.append(trainingSet[0])
# Define the password array.》》》加载主机密码信息为数组
patch_file_name1="tmp_password.txt"
inFile1= open(patch_file_name1,'r')
password = []
for line2 in open(patch_file_name1):
trainingSet = line2.split('\n')
password.append(trainingSet[0])
username = 'oracle'》》》因为都是Oracle用户,只设置为唯一变量即可,不需要设置为数组用户信息
port = 22》》》因为调用主机的都是22号端口,只设置为唯一变量即可
num = 0》》》因为涉及到循环执行命令,设置num初始变量为0作为循环参考数值
s = paramiko.SSHClient()》》》调用paramiko模块中的SSH函数
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())》》》安全性以加密和认证的方式远程登录主机服务器
sshcmd=raw_input("Enter your sql_text: ");》》》设置交互式命令变量,可以是主机可执行的任何变量命令
for hostname in ipadress:》》》循环存在主机信息变量
print("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------")
print("----------------------------------------------------- IP message:"+ str(hostname).ljust(15) +" ----------------------------------------------")》》》输出主机信息作为唯一标识
s.connect(hostname = hostname, port = port, username = username, password = str(password[num]))》》》登录主机
stdin, stdout, stderr = s.exec_command(sshcmd)》》》调用上面交互式执行的主机命令
print stdout.read()
print stderr.read()》》》输出执行命令信息
num += 1
s.close()》》》关闭paramiko模块中的SSH函数
【问题思考】
- 存在系统版本限制,需要安装多个模块;
- 存在数据库版本限制,如果调用数据库命令,需要设置环境变量;
- 存在安全性限制,用户及密码信息需要及时手动清理,可手动加载主机信息文件。
【总结】
- 实现交互式在多个主机需要检查主机命令层面信息,提高信息查询效率非常明显。
- 本次脚本涉及调用Oracle用户的变量,对用户的变量设置标准有较大的要求。