Python实现Linux主机自动创建互信
2017-03-11 00:00
405 查看
摘要: linux,ssh-keygen,python
描述:大数据平台存在100+主机,需要给指定用户创建互信,实现集群内ssh免密码登录。
工具:python,paramiko,multiprocessing
原理:利用paramiko模拟ssh登录执行命令并获取返回结果,利用multiprocessing实现多进程,提高执行效率
运行流程:[检测主机存活]->[检测主机是否存在公钥]->[不存在公钥主机执行ssh-keygen命令]->[获取每台主机公钥]->[分发公钥至每台主机]
实现代码:
注:
(1)依赖的conf文件参考前两章中配置文件生成。
(2)代码在小集群中运行通过,可能存在BUG,如有发现请反馈,谢谢。
描述:大数据平台存在100+主机,需要给指定用户创建互信,实现集群内ssh免密码登录。
工具:python,paramiko,multiprocessing
原理:利用paramiko模拟ssh登录执行命令并获取返回结果,利用multiprocessing实现多进程,提高执行效率
运行流程:[检测主机存活]->[检测主机是否存在公钥]->[不存在公钥主机执行ssh-keygen命令]->[获取每台主机公钥]->[分发公钥至每台主机]
实现代码:
#!/usr/bin/env python #-*- coding:utf-8 -*- #auth:dWX278035 #update:2017/2/22 10:12 #description:Flasky import os,paramiko,sys,time,ConfigParser,subprocess from multiprocessing import Process,Pool import base64 ''' 描述:主机互信自动创建 使用方法:python linuxMutualTrust.py test.conf 参数描述:主机列表conf文件 注: (1)主机不存活不建立互信 (2)主机存在公钥则不会重复生成,自动读取已有公钥 (3)若存在互信,脚本不会清除authorized_keys,会追加公钥至authorized_keys文件 ''' ''' 主机存活检测命令''' pingCheck=['ping','-c','3','-i','0.2','-W','1'] ''' ssh-keygen 命令 ''' keygenCmd='''ssh-keygen -q -t rsa -P '' -f ~/.ssh/id_rsa && echo yes || echo no''' ''' 读取pub文件 ''' readPubCmd='''test -f ~/.ssh/id_rsa.pub && cat ~/.ssh/id_rsa.pub || echo ''' ''' 查看pub文件是否存在 ''' testExistsCmd='''test -f ~/.ssh/id_rsa.pub && echo yes || echo no''' ''' 追加公钥至authorized_keys中''' addKeyCmd='''echo %s >> ~/.ssh/authorized_keys && echo yes || echo no''' ''' 消息返回分隔符,应尽量复杂''' _mess_part='''|+|''' ''' 进程池大小 ''' PROCESSES=30 ''' 初始化配置文件 ''' class InitConf: def __init__(self,conf_file): try: file_path = os.path.join(sys.path[0],conf_file) self.cf = ConfigParser.SafeConfigParser() self.cf.read(conf_file) except Exception as e: Log('RED','ConfigParserError:%s' % (str(e))) sys.exit(1) ''' 读取文件配置信息 ''' def readConf(self): Log('GREEN','开始初始化配置信息...') hosts=[] try: opts = eval(self.cf.get('host','connList')) for opt in opts: host = [] s = eval(self.cf.get('information',opt)) host.append(s['ip']) host.append(s['user']) host.append(base64.b64decode(s['password'])) host.append(s['port']) hosts.append(host) except Exception as e: Log('RED','ReadConfError:%s' % (str(e))) sys.exit(1) return hosts '''检测主机存活 ''' def checkAloneHost(host_info): ip = host_info[0] _pingCheck = pingCheck _pingCheck.append(ip) try: child = subprocess.Popen(_pingCheck,stdout=subprocess.PIPE) _status = child.communicate() transmitted = _status[0].split('\n')[-3].split(',')[0].split()[0] received = _status[0].split('\n')[-3].split(',')[1].split()[0] if int(transmitted) != int(received) : Log('RED','[%s]:[%s] %s' % (ip,'ping',str(e))) return '%s%s%s' %(ip,_mess_part,'no') else: return '%s%s%s' %(ip,_mess_part,'yes') except Exception: return '%s%s%s' %(ip,_mess_part,'no') ''' 多进程检测主机存活状态''' def checkHostsAlive(server_list): Log('GREEN','开始检测主机是否存活...') result,_alive,_died=[],[],[] p = Pool(processes = PROCESSES) for h in server_list: result.append(p.apply_async(checkAloneHost,[h,])) p.close() p.join() for rs in result: if rs is None: break ip,status = rs.get().strip().split(_mess_part) if status == 'yes': _alive.append(ip) else: _died.append(ip) return _alive,_died ''' 初始化ssh服务 ''' def init_server(): server = paramiko.SSHClient() server.load_system_host_keys() server.set_missing_host_key_policy(paramiko.AutoAddPolicy()) return server ''' 定义日志输出格式 ''' def Log(type,msg): date_detail = time.strftime('%Y-%m-%d %H:%M:%S') logText='[%s] %s' %(date_detail,msg) if type == 'NOMAL': print '\033[32;1m%s\033[0m' %(msg) elif type == 'GREEN': print '\033[32;1m[INFO ] %s\033[0m' %(logText) elif type == 'RED': print '\033[31;1m[ERROR] %s\033[0m' %(logText) elif type == 'YELLOW': print '\033[33;1m[WARN ] %s\033[0m' %(logText) ''' 命令执行函数 ''' def ssh_run(host_info,cmd,server): try: ip,username,password,port= host_info[0],host_info[1],host_info[2],host_info[3] server.connect(ip,int(port),username,password,timeout=5) stdin,stdout,stderr = server.exec_command(cmd) return '%s%s%s' %(ip,_mess_part,stdout.read().replace('\n',' ')) except Exception as e: Log('RED','[%s]:[%s] %s' % (ip,cmd,str(e))) return '%s%s%s' %(ip,_mess_part,'error') ''' 执行命令 ''' def exec_pools_cmd(server_list,cargs): result=[] p = Pool(processes = PROCESSES) for h in server_list: result.append(p.apply_async(ssh_run,[h,] + cargs)) p.close() p.join() return result ''' 判断当前用户.ssh目录下公钥是否存在 ''' def checkExistsKey(server_list,server): _exists,_not_exists,_error=[],[],[] result = exec_pools_cmd(server_list,[testExistsCmd,server]) for rs in result: ip,status = rs.get().strip().split(_mess_part) if status == 'yes': _exists.append(ip) elif status == 'no': _not_exists.append(ip) else: _error.append(ip) return _exists,_not_exists,_error ''' 读取当前用户.pub文件,并返回结果信息''' def readPubInfo(server_list,server): Log('GREEN','开始读取主机id_rsa.pub文件...') _authorized_keys=[] result = exec_pools_cmd(server_list,[readPubCmd,server]) for rs in result: ip,keys = rs.get().split(_mess_part) if keys != "": _authorized_keys.append(keys) else: Log('RED','[%s] %s' %(ip,'Read id_rsa.pub error!')) return _authorized_keys ''' 登录主机执行ssh-keygen命令 ''' def exec_ssh_keygen(server_list,server): Log('GREEN','开始执行ssh-keygen...') _success,_error=[],[] result = exec_pools_cmd(server_list,[keygenCmd,server]) for rs in result: ip,status = rs.get().strip().split(_mess_part) if status == 'yes': _success.append(ip) else: _error.append(ip) return _success,_error ''' 检查主机是否存在公钥 ''' def checkStatus(server_list,server): _exists_hosts,_not_exists_hosts,_error_hosts = [],[],[] print('\n-------------检查结果----------------') _exists,_not_exists,_error = checkExistsKey(server_list,server) print('已存在:[%s]个' %(len(_exists))) if len(_not_exists_hosts) >0 : print('不存在:[%s]' %(len(_not_exists))) if len(_error) > 0 : print('执行命令错误主机:%s' %(_error)) print('-------------------------------------\n') for se in server_list: if se[0] in _not_exists: _not_exists_hosts.append(se) elif se[0] in _exists: _exists_hosts.append(se) else: _error_hosts.append(se) return _exists_hosts,_not_exists_hosts,_error_hosts ''' 将公钥写入authorized_keys''' def writeKeys(server_list,server,keys): Log('GREEN','开始写入authorized_keys...') add_cmd = addKeyCmd %(keys) result = exec_pools_cmd(server_list,[add_cmd,server]) for rs in result: ip,status = rs.get().strip().split(_mess_part) if status != 'yes': Log('RED','[Write keys error] %s %s' %(ip,status)) ''' 主函数 ''' def main(conf_name): p = InitConf(conf_name) server_list = p.readConf() server = init_server() alive_host = [] _alive,_died = checkHostsAlive(server_list) Log('GREEN','存活主机: %s/%s ' %(len(_alive),len(server_list))) if len(_died) > 0: Log('RED','死亡主机列表: %s') %(str(_died)) for _x in server_list: if _x[0] in _alive: alive_host.append(_x) else: alive_host = server_list Log('GREEN','执行前ssh-keygen检查...') chk_ok_hosts,chk_need_hosts,chk_error_hosts=checkStatus(alive_host,server) if len(chk_need_hosts) > 0: _exec_success,_exec_error = exec_ssh_keygen(chk_need_hosts,server) Log('GREEN','执行成功:[%s]个' %(len(_exec_success))) if len(_exec_error) > 0 : Log('RED','执行ssh-keygen失败列表:%s' %(_exec_errror)) Log('GREEN','执行后ssh-keygen检查...') chk_ok_hosts,chk_need_hosts,chk_error_hosts=checkStatus(alive_host,server) if len(chk_error_hosts) > 0: Log('RED','互信失败列表:%s' %(chk_error_hosts)) else: Log('YELLOW','所有主机均存在公钥!!!') _authorized_keys = readPubInfo(chk_ok_hosts,server) for keys in _authorized_keys: writeKeys(chk_ok_hosts,server,keys) ''' 程序入口 ''' if __name__ == '__main__': if len(sys.argv) < 2: Log('RED','Usage: python %s test.conf' %(sys.argv[0])) sys.exit(1) else: conf_name = sys.argv[1] main(conf_name)
注:
(1)依赖的conf文件参考前两章中配置文件生成。
(2)代码在小集群中运行通过,可能存在BUG,如有发现请反馈,谢谢。
相关文章推荐
- nagios监控linux主机、web等各种服务,并实现飞信自动报警
- Python:在Linux下创建一个脚本并且自动修改权限,可以选择路径。批量生成脚本 。
- linux实现kickstart无人值守并自动分配主机名【实验】
- 通过crond自动运行Python脚本实现多台linux服务器的监控
- Python 使用paramiko实现远程登录Linux主机并执行命令和操作
- nagios监控linux主机、web等各种服务,并实现飞信自动报警
- linux 实现自动创建ftp用户并创建文件夹
- Python获取linux主机ip的简单实现方法
- 使用Python创建.sd服务定义文件,实现脚本自动发布ArcGIS服务
- linux ,叫你如何实现脚本自动创建自己专属迷你小linux(一)
- Putty实现自动登陆远程Linux主机的方法
- linux 下写python脚本实现自动补全( 我51论坛也有)
- Linux下使用crontab命令以及Python脚本实现自动签到
- nagios监控linux主机、web等各种服务,并实现飞信自动报警
- nagios监控linux主机、web等各种服务,并实现飞信自动报警
- scp在linux中实现两台主机传件--互信无需输入密码
- Putty实现自动登陆远程Linux主机的方法
- Unet用代码实现 自动加入/创建主机
- linux下实现shell脚本自动连接mongodb数据库并创建索引
- 通过 python 打开 SecureCRT 软件并实现自动连接主机