python实现跳板机,,公司有1000多台服


公司有1000多台服务器,线上机器都是禁止root登录的,所以平时是用普通用户登录,然后在su到root,密码都是在excel表中存的,这样登录一台机器,输两次命令,搜两次密码,实在很麻烦,而且密码表都在大家手中不易控制,所以把密码放到数据库中,每次ssh登录自动去数据库中查密码,然后发送密码,实现交互,这样既方便了我们,又控制的密码,脚本的核心是用pexpect来实现交互,用MySQLdb去查询密码,把代码保存为zssh 给个执行权限,建立数据库,把密码表导入到数据库中,就可以使用zssh ip 来登录了,是不是很爽,来试试吧!

pexpect的用法看http://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/

代码见附件

代码如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130#!/usr/local/bin/python# coding: utf-8##导入模块importosimportsysimportpexpectimportMySQLdbimportstructimportfcntlimporttermiosimportsignal##传入的参数opt=sys.argv##如果没跟参数,就提示iflen(opt)==1:print‘‘‘----------------------------‘Useage: ./zssh.py ServerIP‘----------------------------‘‘‘sys.exit(2)##下面两个函数更改pexpect模拟的窗口大小,##参见http://guweigang.com/blog/2012/10/25/using-python-ssh-landing-module-performs-pexpect/defsigwinch_passthrough (sig, data):winsize=getwinsize()globalfoofoo.setwinsize(winsize[0],winsize[1])defgetwinsize():if‘TIOCGWINSZ‘indir(termios):TIOCGWINSZ=termios.TIOCGWINSZelse:TIOCGWINSZ=1074295912L# Assumes=struct.pack(‘HHHH‘,0,0,0,0)x=fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s)returnstruct.unpack(‘HHHH‘, x)[0:2]##传入的ipip=opt[1]##用MySQLdb驱动连接mysqlconn=MySQLdb.connect(host=‘localhost‘, user=‘root‘, passwd=‘Te62S#^t‘, db=‘sa‘)cursor=conn.cursor()##查找该ip的普通用户名,密码,还有root的密码,用来ssh连接cursor.execute(‘select muser,mpass,rpass from password where ip=%s‘, ip)result=cursor.fetchall()##如果没在数据库中发现该ip信息,提示用户输入,并保存,如果发现就准备连接iflen(result)==0:muser=raw_input(‘输入用户名:‘)mpass=raw_input(‘输入用户密码: ‘)rpass=raw_input(‘输入root密码: ‘)cursor.execute(‘insert into password values (%s,%s,%s,%s)‘, (ip, muser, mpass, rpass))conn.commit()eliflen(result)==1:muser=result[0][0]mpass=result[0][1]rpass=result[0][2]##用pexpect模块的spawn类,连接sshfoo=pexpect.spawn(‘ssh %[email protected]%s‘%(muser,ip))whileTrue:##期望得到列表里的东西index=foo.expect([‘continue‘,‘assword‘, pexpect.EOF, pexpect.TIMEOUT],timeout=10)##如果得到的是continue,也就是第一次连接输入yes/no那,那就发送yesifindex==0:foo.sendline(‘yes‘)continue##如果是提示输入password,那就发送密码elifindex==1:foo.sendline(mpass)##发送密码后有两种情况,登录成功或密码错误index2=foo.expect([‘password‘,‘]\$‘])##如果得密码正确ifindex2==1:print‘%s 登录成功‘%muserbreak##如果密码错误,提示输入密码elifindex2==0:whileTrue:muser=raw_input(‘输入用户名:‘)mpass=raw_input(‘用户密码不对,重新输入: ‘)foo.sendline(mpass)index3=foo.expect([‘]\$‘,‘assword‘], timeout=5)##如果密码对了,就保存到数据库ifindex3==0:cursor.execute(‘update sys_pass set muser=%s, mpass=%s where ip=%s ‘, (muser, mpass, ip))conn.commit()foo.sendline(‘‘)break##如果不对,再循环一次else:continueelse:print‘连接超时‘break##下面su 到root与上面类似whileTrue:foo.expect(‘$‘)foo.sendline(‘su - root‘)#index4 = foo.expect([‘口令‘, ‘密码‘, ‘assword‘, pexpect.TIMEOUT, pexpect.EOF],timeout=5)foo.sendline(rpass)index5=foo.expect([‘]#‘,‘monitor‘, pexpect.EOF, pexpect.TIMEOUT], timeout=5)ifindex5==0:print‘root 登录成功‘foo.sendline(‘‘)breakelifindex5==1:whileTrue:rpass=raw_input(‘root密码不对,请输入: ‘)foo.expect(‘$‘)foo.sendline(‘su - root‘)#index6 = foo.expect([‘口令‘, ‘密码‘, ‘assword‘, pexpect.TIMEOUT, pexpect.EOF],timeout=5)foo.sendline(rpass)index7=foo.expect([‘]#‘,‘monitor‘, pexpect.EOF, pexpect.TIMEOUT], timeout=5)ifindex7==0:cursor.execute(‘update sys_pass set rpass=%s where ip=%s‘, (rpass, ip))conn.commit()print‘root 登录成功‘breakelifindex7==1:continueelse:print‘error‘else:print‘error‘##这个是利用那两个函数来调节子线程窗口大小signal.signal(signal.SIGWINCH, sigwinch_passthrough)size=getwinsize()foo.setwinsize(size[0], size[1])##进入interact交互模式foo.interact()pass

数据库建立

12createdatabasesa;createtablepassword(ipvarchar(15)primarykeynotnull, muservarchar(15), mpassvarchar(30), rpassvarchar(30));

将密码表的中的ip,普通用户名,密码,root密码插入库中我用的是一个脚本

1234567891011121314151617181920212223#!/usr/local/bin/pythonimportMySQLdbconn=MySQLdb.connect(host=‘localhost‘, user=‘root‘, passwd=‘Te62S#^t‘, db=‘sa‘)cursor=conn.cursor()f=open(‘passwd.txt‘)num=0foriinf:ilist=i.split()iflen(ilist)==4:ip=ilist[0]muser=ilist[1]mpass=ilist[2]rpass=ilist[3]try:cursor.execute(‘insert into password values (%s,%s,%s,%s)‘, (ip, muser, mpass, rpass))num+=1except:passprintnumconn.commit()cursor.close()conn.commit()

将密码保存到passwd.txt格式类下面的格式,执行脚本就可以了

IP 普通用户名 密码 root密码

202.106.0.20 monitor asdf123Sfad f(adfasdfasdf

202.106.0.21 zhswred hathell oworld

python实现跳板机

评论关闭