公司有1000多台伺服器,線上機器都是禁止root登入的,所以平時是用普通使用者登入,然後在su到root,密碼都是在excel表中存的,這樣登入一台機器,輸兩次命令,搜兩次密碼,實在很麻煩,而且密碼錶都在大家手中不易控制,所以把密碼放到資料庫中,每次ssh登入自動去資料庫中查密碼,然後發送密碼,實現互動,這樣既方便了我們,又控制的密碼,指令碼的核心是用pexpect來實現互動,用MySQLdb去查詢密碼,把代碼儲存為zssh 給個執行許可權,建立資料庫,把密碼錶匯入到資料庫中,就可以使用zssh ip 來登入了,是不是很爽,來試試吧!
pexpect的用法看http://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/
代碼見附件
代碼如下:
#!/usr/local/bin/python# coding: utf-8##匯入模組import osimport sysimport pexpectimport MySQLdbimport structimport fcntlimport termiosimport 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]##傳入的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資訊,提示使用者輸入,並儲存,如果發現就準備串連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類,串連sshfoo = 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) primary key not null, muser varchar(15), mpass varchar(30), rpass varchar(30));
將密碼錶的中的ip,普通使用者名稱,密碼,root密碼插入庫中我用的是一個指令碼
#!/usr/local/bin/pythonimport MySQLdbconn = MySQLdb.connect(host='localhost', user='root', passwd='Te62S#^t', db='sa')cursor = conn.cursor()f = open('passwd.txt')num = 0for 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: passprint num conn.commit()cursor.close()conn.commit()
將密碼儲存到passwd.txt格式類下面的格式,執行指令碼就可以了
IP 普通使用者名稱 密碼 root密碼
202.106.0.20 monitor asdf123Sfad f(adfasdfasdf
202.106.0.21 zhswred hathell oworld
本文出自 “Free Linux,Share Linux” 部落格,請務必保留此出處http://laoguang.blog.51cto.com/6013350/1328891