Python笔记:python实现跳板机

原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://laoguang.blog.51cto.com/6013350/1328891

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

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

代码见附件

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/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
     =  struct.pack( 'HHHH' 0 0 0 0 )
     =  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


数据库建立

1
2
create  database  sa;
create  table  password  (ip  varchar (15)  primary  key  not  null , muser  varchar (15), mpass  varchar (30), rpass  varchar (30));


 
 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/local/bin/python
import  MySQLdb
conn  =  MySQLdb.connect(host = 'localhost' , user = 'root' , passwd = 'Te62S#^t' , db = 'sa' )
cursor  =  conn.cursor()
=  open ( 'passwd.txt' )
num  =  0
for  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.20 monitor asdf123Sfad f(adfasdfasdf

202.106.0.21 zhswred hathell oworld




本文出自 “Free Linux, Share Linux” 博客,请务必保留此出处http://laoguang.blog.51cto.com/6013350/1328891

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值