介绍
本文介绍使用python 自动连ssh,并通过正则处理返回值。
通过这段代码,可以使一些繁杂的工作,变成比较简单以及自动化。
代码
#!/usr/bin/env python
import pexpect
import signal, fcntl, termios, struct, sys
global_pexpect_instance = None
# 当窗口大小有改变时
def sigwinch_passthrough(sig, data):
# Set terminal size
if 'TIOCGWINSZ' in dir(termios):
TIOCGWINSZ = termios.TIOCGWINSZ
else:
TIOCGWINSZ = 1074295912
s = struct.pack ("HHHH", 0, 0, 0, 0)
a = struct.unpack ('HHHH', fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ , s))
global global_pexpect_instance
global_pexpect_instance.setwinsize(a[0],a[1])
# 处理返回值,并输入密码
def ssh_password(child,password,other=None):
global base_path
ssh_newkey = 'Are you sure you want to continue connecting'
while True:
step=[pexpect.TIMEOUT, ssh_newkey, '[pP]assword:.*', '.*[\$#] '];
if other:
step.append(other);
i = child.expect(step,timeout=120)
print "expect:"+step[i];
if i == 0:
print child.before,child.befor
print child.before,child.after
print 'Time out'
return False;
if i == 1:
child.sendline('yes')
if i == 2:
child.sendline(password)
if i == 3:
print child.before,child.after
return True;
return True;
# 发送命令
def ssh_command(host, user, password, post_command=None):
global global_pexpect_instance
print 'ssh -l %s %s'%(user, host);
child = pexpect.spawn('ssh -l %s %s'%(user, host))
global_pexpect_instance = child
signal.signal(signal.SIGWINCH, sigwinch_passthrough)
if not ssh_password(child,password):
return None;
if post_command :
child.sendline(post_command);
return child;
# 等待返回,当非字符交互界面时用:如执行命令,等待结束
def ssh_wait(child,other=None):
step=[pexpect.TIMEOUT, '.*[\$#]'];
if other:
step.append(other);
i = child.expect(step)
print child.before
print child.after
# 执行远程登录,如果有命令则直接返回,如果不是执行命令,则进入字符交互界面
def ssh(host,user,password,post_command=None):
child=ssh_command(host,user,password,post_command)
sigwinch_passthrough(None, None)
if child==None:
return
if post_command==None:
child.interact(chr(0x1e)) # ctrl+~
else:
ssh_wait(child)
解释
主要思路:
第一步: pexpect 包的spawn 执行ssh 并将用户名和地址填上
第二步:spawn会返回子进程的句柄,通过这个句柄,可以进行发送以及接收返回的字符串
第三步:使用 expect 函数,对返回进行正则匹配
第四步:
expect,会返回命中规则的下标,然后,可以对各种情况进行处理.
比如,在返回 '[pP]assword:.*' 时,发送密码
第五步:
最后,调用interact 进入字符交互界面。然后,就可以手动输入其他命令了。
总结
有了这套工具,可以实现快捷地登录服务器,或者是以另外一种鉴权方式登录服务器(如短信)
比如,我当前的使用是,快捷登录,比如输入 myssh cmky 就可以登录我的服务器了。
相当方便,如果使用linux 还可以和tmux 一同工作。
番外篇:与tmux 一同工作
我们将以上脚本保存为一个叫myssh 的可执行文件,并保存在可执行目录下
我们添加一个脚本,叫tssh :
echo $1
ifattach=0;
tmux -L `whoami` list-sessions
if [[ $? -ne 0 ]]; then
echo "mytmux";
ifattach=1;
tmux -L `whoami` new -d
fi
tmux -L `whoami` neww -n $1 "myssh $1"
if [[ $ifattach -eq 1 ]]; then
echo "attach"
tmux -L `whoami` attach
fi
之所以添加 -L whoami
是为了避免在多用户下,公用tmux 而产生的问题。
保证每个用户一个tmux 服务
注意替换 myssh $1 为你自己的命令