用 python 实现 ssh 登录
我工作上要经常登录大约20台,40多个用户的 AIX 主机.
客户对主机的管理又极乱,有的只能 telnet,大部分可以 ssh,可以 ssh 的又只有一部分用户允许密匙登录.
我手贱,加了密匙登录.所以目前的状况是,有的 ssh 可以直接进去,有的 ssh 要输入密码,有的只能用 telnet.
够乱吧,弄的我极度不爽,安全什么的玩蛋去吧,密码明文保存又怎样,我只要方便.反正是內网.
遂写了以下 python 用来登录:
v 0.3
#!/usr/bin/python
#encoding=utf-8
#file_name=ssh.py
import sys
import os
import pexpect
def init_ssh_info():
ssh_info=[]
f=open(sys.path[0]+'/ssh.ini','r')
for i in f:
ssh_one_info=i.split()
if(len(ssh_one_info)!=0):
ssh_info.append(tuple(i.split()))
f.close()
return sorted(ssh_info, key=lambda by:by[1])
def ssh(user, ip, passwd):
#ssh=pxssh.pxssh()
#ssh.login (ip, user, passwd)
lines=int(os.getenv('LINES'))
columns=int(os.getenv('COLUMNS'))
ssh=pexpect.spawn("ssh -o StrictHostKeyChecking=no '%s@%s'"%(user, ip), timeout = 1)
try:
ssh.expect('.*ssword:', timeout=1)
ssh.sendline(passwd)
ssh.setwinsize(lines, columns)
ssh.interact()
except pexpect.TIMEOUT:
ssh.setwinsize(lines, columns)
ssh.interact()
except pexpect.EOF:
ssh=pexpect.spawn(command="telnet '%s'"%(ip))
ssh.expect('.*login:', timeout=0.5)
ssh.sendline(user)
ssh.expect('.*ssword:', timeout=0.5)
ssh.sendline(passwd)
ssh.setwinsize(lines, columns)
ssh.interact()
except Exception, e:
raise e
def print_info(ssh_info):
for i in ssh_info:
print str(ssh_info.index(i)).ljust(4), i[0].ljust(10), i[1].ljust(16) , i[2].ljust(10), i[3]
def select_nbr(ssh_info):
print_info(ssh_info)
nbr_input=raw_input('序号:')
if(nbr_input=='q'):
exit(0)
if(nbr_input==''):
select_ip(ssh_info)
else:
nbr=int(nbr_input)
if(nbr>(len(ssh_info)-1) or nbr<0):
print '序号的范围只是0到%s,请重新选择'%(len(ssh_info)-1)
select_nbr(ssh_info)
ssh_info_one=ssh_info[nbr]
user = ssh_info_one[0]
ip = ssh_info_one[1]
passwd = ssh_info_one[2]
#ssh(ssh_info_one[0], ssh_info_one[1], ssh_info_one[2])
return user, ip, passwd
def select_ip(ssh_info):
ip_input=raw_input('ip(近似值):')
if(ip_input=='q'):
exit(0)
ssh_info_ip=[]
for i in ssh_info:
index=i[1].find(ip_input)
if(index!=-1):
ssh_info_ip.append(i)
if(len(ssh_info_ip)==0):
print '没找到和这个ip有近似的'
select_nbr(ssh_info)
else:
return select_nbr(ssh_info_ip)
if __name__ == "__main__":
os.environ['LINES'] = '39'
os.environ['COLUMNS'] = '157'
ssh_info=init_ssh_info()
print_info(ssh_info)
user, ip, passwd = select_ip(ssh_info)
ssh(user, ip, passwd)
v 0.2
增加了对登录后窗口大小的设置.
必须在 interact 前执行 setwinsize,早了是不生效的.
没找到怎么直接取 gnome-terminal,的大小.
根据本机的情况,自己在 main 里改一下吧.
#!/usr/bin/python
#encoding=utf-8
#file_name=ssh.py
import sys
import os
import pexpect
import pxssh
def init_ssh_info():
ssh_info=[]
f=open(sys.path[0]+'/ssh.ini','r')
for i in f:
ssh_one_info=i.split()
if(len(ssh_one_info)!=0):
ssh_info.append(tuple(i.split()))
f.close()
return sorted(ssh_info, key=lambda by:by[1])
def ssh(user, ip, passwd):
#ssh=pxssh.pxssh()
#ssh.login (ip, user, passwd)
print os.getenv('LINES')
lines=int(os.getenv('LINES'))
columns=int(os.getenv('COLUMNS'))
ssh=pexpect.spawn("ssh -o StrictHostKeyChecking=no '%s@%s'"%(user, ip))
try:
ssh.expect('.*ssword:', timeout=1)
ssh.sendline(passwd)
ssh.setwinsize(lines, columns)
ssh.interact()
except pexpect.TIMEOUT:
ssh.interact()
except pexpect.EOF:
ssh=pexpect.spawn(command="telnet '%s'"%(ip))
ssh.expect('.*login:', timeout=0.5)
ssh.sendline(user)
ssh.expect('.*ssword:', timeout=0.5)
ssh.sendline(passwd)
ssh.setwinsize(lines, columns)
ssh.interact()
except Exception, e:
raise e
def print_info(ssh_info):
for i in ssh_info:
print str(ssh_info.index(i)).ljust(4), i[0].ljust(10), i[1].ljust(16) , i[2].ljust(10), i[3]
def select_nbr(ssh_info):
print_info(ssh_info)
nbr_input=raw_input('序号:')
if(nbr_input=='q'):
exit(0)
if(nbr_input==''):
select_ip(ssh_info)
else:
nbr=int(nbr_input)
if(nbr>(len(ssh_info)-1) or nbr<0):
print '序号的范围只是0到%s,请重新选择'%(len(ssh_info)-1)
select_nbr(ssh_info)
ssh_info_one=ssh_info[nbr]
ssh(ssh_info_one[0], ssh_info_one[1], ssh_info_one[2])
def select_ip(ssh_info):
ip_input=raw_input('ip(近似值):')
if(ip_input=='q'):
exit(0)
ssh_info_ip=[]
for i in ssh_info:
index=i[1].find(ip_input)
if(index!=-1):
ssh_info_ip.append(i)
if(len(ssh_info_ip)==0):
print '没找到和这个ip有近似的'
select_nbr(ssh_info)
else:
select_nbr(ssh_info_ip)
if __name__ == "__main__":
os.environ['LINES'] = '39'
os.environ['COLUMNS'] = '157'
ssh_info=init_ssh_info()
print_info(ssh_info)
select_ip(ssh_info)
v 0.1
#!/usr/bin/python
#encoding=utf-8
#file_name=ssh.py
import sys
import pexpect
import pxssh
def init_ssh_info():
ssh_info=[]
f=open(sys.path[0]+'/ssh.ini','r')
for i in f:
ssh_one_info=i.split()
if(len(ssh_one_info)!=0):
ssh_info.append(tuple(i.split()))
f.close()
return sorted(ssh_info, key=lambda by:by[1])
def ssh(user, ip, passwd):
#ssh=pxssh.pxssh()
#ssh.login (ip, user, passwd)
ssh=pexpect.spawn("ssh -o StrictHostKeyChecking=no '%s@%s'"%(user, ip))
try:
ssh.expect('.*ssword:', timeout=0.5)
ssh.sendline(passwd)
ssh.interact()
except pexpect.TIMEOUT:
ssh.interact()
except pexpect.EOF:
ssh=pexpect.spawn("telnet '%s'"%(ip))
ssh.expect('.*login:', timeout=0.5)
ssh.sendline(user)
ssh.expect('.*ssword:', timeout=0.5)
ssh.sendline(passwd)
ssh.interact()
except Exception, e:
raise e
def print_info(ssh_info):
for i in ssh_info:
print str(ssh_info.index(i)).ljust(4), i[0].ljust(10), i[1].ljust(16) , i[2].ljust(10), i[3]
def select_nbr(ssh_info):
print_info(ssh_info)
nbr_input=raw_input('序号:')
if(nbr_input=='q'):
exit(0)
if(nbr_input==''):
select_ip(ssh_info)
else:
nbr=int(nbr_input)
if(nbr>(len(ssh_info)-1) or nbr<0):
print '序号的范围只是0到%s,请重新选择'%(len(ssh_info)-1)
select_nbr(ssh_info)
ssh_info_one=ssh_info[nbr]
ssh(ssh_info_one[0], ssh_info_one[1], ssh_info_one[2])
def select_ip(ssh_info):
ip_input=raw_input('ip(近似值):')
if(ip_input=='q'):
exit(0)
ssh_info_ip=[]
for i in ssh_info:
index=i[1].find(ip_input)
if(index!=-1):
ssh_info_ip.append(i)
if(len(ssh_info_ip)==0):
print '没找到和这个ip有近似的'
select_nbr(ssh_info)
else:
select_nbr(ssh_info_ip)
if __name__ == "__main__":
ssh_info=init_ssh_info()
print_info(ssh_info)
select_ip(ssh_info)
文件保存为 ssh.py,在同目录下建一个 ssh.ini,格式如下:
用户 ip 密码 说明
中间用空格或tab分隔.
比如
bigzhu 192.168.1.2 123456 例子1
flyzhu 192.168.1.3 123456 例子2
pxssh 用不起来,懒得深究了.
- ip 我记得部分,所以加了近似值过滤,不爽的同学可以将之去了.
- 网络不好的同学可以把 timeout 增大.
- ssh.expect('.*ssword:', timeout=0.5) 超时,我就认为是遇到了我加过密匙登录的,直接interact,不适合的同学可以改之
- pexpect.EOF 我就认为是遇到只能 telnet 的主机了,不适合的同学可以改之
- 不想把密码打到屏幕上的把 i[2].ljust(10) 去掉.