公司有1000多台服务器,线上机器都是禁止root登录的,所以平时是用普通用户登录,然后在su到root,密码都是在excel表中存的,这样登录一台机器,输两次命令,搜两次密码,实在很麻烦,有一天备份6台机器上的redis,登录就把我登录烦了,于是就用python来实现登录操作,密码表存到mysql中,用python的pexpect来实现交互。
pexpect的用法看http://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/
最后用 ./passwdbox.py ip即可自动登录
#!/usr/local/bin/python # coding: utf-8 ##导入模块 import os import sys import pexpect import MySQLdb import struct import fcntl import termios import signal ##传入的参数 opt = sys.argv ##如果没跟参数,就提示 if len(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/ def sigwinch_passthrough (sig, data): winsize = getwinsize() global foo foo.setwinsize(winsize[0],winsize[1]) def getwinsize(): if 'TIOCGWINSZ' in dir(termios): TIOCGWINSZ = termios.TIOCGWINSZ else: TIOCGWINSZ = 1074295912L # Assume s = struct.pack('HHHH', 0, 0, 0, 0) x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) return struct.unpack('HHHH', x)[0:2] ##传入的ip ip = opt[1] ##用MySQLdb驱动连接mysql conn = 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信息,提示用户输入,并保存,如果发现就准备连接 if len(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() elif len(result) == 1: muser = result[0][0] mpass = result[0][1] rpass = result[0][2] ##用pexpect模块的spawn类,连接ssh foo = pexpect.spawn('ssh %s@%s' % (muser,ip)) while True: ##期望得到列表里的东西 index = foo.expect(['continue', 'assword', pexpect.EOF, pexpect.TIMEOUT],timeout=10) ##如果得到的是continue,也就是第一次连接输入yes/no那,那就发送yes if index == 0: foo.sendline('yes') continue ##如果是提示输入password,那就发送密码 elif index == 1: foo.sendline(mpass) ##发送密码后有两种情况,登录成功或密码错误 index2 = foo.expect(['password', ']$']) ##如果得密码正确 if index2 == 1: print '%s 登录成功' % muser break ##如果密码错误,提示输入密码 elif index2 == 0: while True: muser = raw_input('输入用户名:') mpass = raw_input('用户密码不对,重新输入: ') foo.sendline(mpass) index3 = foo.expect([']$', 'assword'], timeout=5) ##如果密码对了,就保存到数据库 if index3 == 0: cursor.execute('update sys_pass set muser=%s, mpass=%s where ip=%s ', (muser, mpass, ip)) conn.commit() foo.sendline('') break ##如果不对,再循环一次 else: continue else: print '连接超时' break ##下面su 到root与上面类似 while True: 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) if index5 == 0: print 'root 登录成功' foo.sendline('') break elif index5 == 1: while True: 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) if index7 == 0: cursor.execute('update sys_pass set rpass=%s where ip=%s', (rpass, ip)) conn.commit() print 'root 登录成功' break elif index7 == 1: continue else: print 'error' else: print 'error' ##这个是利用那两个函数来调节子线程窗口大小 signal.signal(signal.SIGWINCH, sigwinch_passthrough) size = getwinsize() foo.setwinsize(size[0], size[1]) ##进入interact交互模式 foo.interact() pass
数据库建立
create database sa; create table password (ip varchar(15), muser varchar(15), mpass varchar(30), rpass varchar(30));
将密码表的中的ip,普通用户名,密码,root密码插入库中我用的是一个脚本
#!/usr/local/bin/python import MySQLdb conn = MySQLdb.connect(host='localhost', user='root', passwd='Te62S#^t', db='sa') cursor = conn.cursor() f = open('passwd.txt') num = 0 for i in f: ilist = i.split() if len(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 += 1 except: pass print num conn.commit() cursor.close() conn.commit()
将密码保存到passwd.txt格式类似
IP普通用户名密码root密码
202.106.0.20monitorasdf123Sfadf(adfasdfasdf
202.106.0.21zhswredhathelloworld