码迷,mamicode.com
首页 > 编程语言 > 详细

python学习之路(二)开发批量主机管理工具

时间:2017-06-20 00:15:44      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:erro   passwd   obj   返回结果   输出   exec   toad   remote   src   

大概思路:

理想效果就是达到类似于saltstack或者是ansible类似的一点小功能,比如 在命令行下输入python3 automatic.py -g dsp -c ‘w‘

输出:

b‘ 18:24:20 up 3:44, 2 users, load average: 0.00, 0.00, 0.00\nUSER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\nroot pts/0 192.168.0.101 17:26 4:11 0.02s 0.02s -bash\nroot pts/2 192.168.0.101 17:24 1.00s 0.51s 0.12s python3 automat\n‘

使用到的模块:paramiko:用于远程执行命令,支持密钥和用户密码登录

                        optparse:解析命令行

       logging:记录日志

       configparser:解析配置文件

       multiprocessing:启用多进程方式

 目录结构如下:技术分享

 

conf是默认配置文件,log是默认日志文件,automatic主程序,logger日志程序

源码如下:automatic

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import paramiko
from  optparse import OptionParser
import configparser
import os,sys
from multiprocessing import Pool
import logger   #插入日志模块
‘‘‘默认配置文件路径和日志文件路径‘‘‘
CONF_PATH = os.path.abspath(os.path.join(os.path.dirname(‘.‘),‘conf‘))
LOG_PATH = os.path.abspath(os.path.join(os.path.dirname(‘.‘),‘log‘))
‘‘‘解析配置文件,设置默认sections和options,pkey_file指定密钥文件名,fork表示默认开启5个进程‘‘‘
def ConfigParser(group):
    config = configparser.ConfigParser()
    config[‘DEFAULT‘] = {‘user‘:‘root‘,
                          ‘port‘:22,
                          ‘passwd‘:‘123456‘,
                          ‘pkey_file‘:‘‘,
                          ‘host‘: ‘‘

}
    config[‘default‘] = {‘conf_path‘:CONF_PATH,
                         ‘log_path‘: LOG_PATH,
                         ‘fork‘:5
}
    if not os.path.exists(CONF_PATH):    #判断配置文件是否存在,不存在创建并写入默认配置
        fp = open(CONF_PATH,‘w‘)
        config.write(fp)
        fp.close()
    else:
        config.read(CONF_PATH)             #读取配置文件,获取到分组的options的各项值
        try:
            section = config.sections()
            ip = config.get(group,‘host‘)
            user = config.get(group,‘user‘)
            port = config.get(group,‘port‘)
            passwd = config.get(group,‘passwd‘)
            pkey_file = config.get(group,‘pkey_file‘)
            fork = config.get(‘default‘,‘fork‘)
            log_path = config.get(‘default‘,‘log_path‘)   
        except Exception:
            print ("group is not exists")
        else:
            return section,ip,user,port,passwd,pkey_file,fork,log_path

def remote_cmd(ip,user,passwd,cmd,pkey_file=None):    #调用ssh客户端执行命令返回结果
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    if pkey_file:                                             #如果传入了密钥文件,采用密钥方式登录
        key = paramiko.RSAKey.from_private_key_file(pkey_file)
        ssh.connect(hostname=ip,username=user,pkey=key)
    ssh.connect(hostname=ip,username=user,password=passwd)
    stdin,stdout,stderr = ssh.exec_command(cmd)
    if stdout:
        result = stdout.read()

    else:
        result = stderr.read()
    return result
‘‘‘调用sftp进行上传下载文件‘‘‘
class SFTP(object):
    def __init__(self,ip,port,user,passwd,src_file,dst_file,pkey_file=None):
        self.ip = ip
        self.port = int(port)
        self.user = user
        self.passwd = passwd
        self.src_file = src_file
        self.dst_file = dst_file
        self.pkey_file = pkey_file
    def remote_transport(self):
        s = paramiko.Transport((self.ip,self.port))
        if self.pkey_file:   #如果传入了密钥文件,采用密钥方式登录
            key = paramiko.RSAKey.from_private_key_file(self.pkey_file)
            s.connect(username=self.user,password=None,pkey=key)
        s.connect(username=self.user,password=self.passwd)
        sftp = paramiko.SFTPClient.from_transport(s)
        return sftp
    def get(self):     #下载文件
        sftp = self.remote_transport()
        sftp.get(self.src_file,self.dst_file)

    def put(self):  #上传文件
        sftp = self.remote_transport()
        sftp.put(self.src_file,self.dst_file)
‘‘‘解析命令行,使用optparse,我用的python3.6版本‘‘‘
def opt():
    parser = OptionParser("Usage: %prog [-g GROUP] [-c COMMAND]")
    parser.add_option(‘-g‘,‘--group‘,
                      dest = ‘group‘,
                      action = ‘store‘,
                      default = True,
                      help=‘GROUP‘)
    parser.add_option(‘-c‘,‘--command‘,
                      dest = ‘command‘,
                      action=‘store‘,
                      default = True,
                      help="COMMAND")
    options,args = parser.parse_args()
    return options,args
‘‘‘根据-c 后面跟的命令判断是进行ssh远程执行命令还是使用sftp上传下载文件操作,并记录日志,src为源文件,dst为目标文件,f是进行get还是put,get表示下载,put表示上传‘‘‘
def multi_pool(cmd,ip,user,port,passwd,pkey_file,log_path):
    if cmd.startswith(‘get‘) or cmd.startswith(‘put‘):
        src = cmd.split()[1]
        dst = cmd.split()[2]
        f = cmd.split()[0]
        sf = SFTP(ip,port,user,passwd,src,dst,pkey_file)
        if hasattr(sf,f):     #使用反射,减少判断
            func = getattr(sf,f)
            func()
            logger.loggs("%s %s" % (ip,cmd),log_path)
    else:
        result = remote_cmd(ip,user,passwd,cmd,pkey_file)
        logger.loggs("%s %s" % (ip,cmd),log_path)
        print(result)
‘‘‘主函数,进行读取命令行参数以及获取配置文件的各项值,开启多进程,使用进程池‘‘‘
def main():
    options,args = opt()
    groups = options.group
    cmd = options.command
    try:
        sec,ip,user,port,passwd,pkey_file,fork,log_file = ConfigParser(groups)
    except Exception:
        print("configparser error")
    else:
        p = Pool(int(fork))
        if groups in sec:
            for i in ip.split(‘,‘):
                p.apply_async(func=multi_pool,args=(cmd,i,user,port,passwd,pkey_file,log_file))
            p.close()
            p.join()


if __name__ ==‘__main__‘:
    main()

 logger源码:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import logging
‘‘‘msg是需要记录的日志信息,f是日志路径‘‘‘
def loggs(msg,f):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler(f)
    fh.setLevel(logging.DEBUG)
    formatter = logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s)   #日志格式
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    logger.debug(msg)

if __name__ == __main__:
    msg = ‘‘
    f = ‘‘
    loggs(msg,f)

基本实现了预期的功能,由于时间原因流程图就没画,使用python3.6版本在centos6.7版本运行成功

 

python学习之路(二)开发批量主机管理工具

标签:erro   passwd   obj   返回结果   输出   exec   toad   remote   src   

原文地址:http://www.cnblogs.com/wrlinux/p/7051170.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!