pexpect介绍

使用过perl同学都知道expect模块,可以方便对另外主机进行自动交互。
@扶凯 代码实例:

 
#!/usr/bin/perl
use Expect;
$Expect::Log_Stdout = 1;
 
$ENV{TERM} = "vt100";
 
my ($host,$pass) = ("remotehostname","yourpassword");
my $exp = Expect->new;
$exp = Expect->spawn("ssh -l yourusername $host");
$exp->log_file("output.log", "w");
$exp->expect(2,[
                    qr/password:/i,
                    sub {
                            my $self = shift ;
                            $self->send("$pass\n");
                            exp_continue;
 
                        }
                ],
                [
                    'connecting (yes/no)',
                    sub {
                            my $self = shift ;
                            $self->send("yes\n");
                         }
                ]
            );
$exp->send("uptime\n") if ($exp->expect(undef,'$'));
$exp->send("exit\n") if ($exp->expect(undef,'$'));
$exp->log_file(undef);
$perl ssh.pl
Password: 
Last login: Sun Jul 29 12:17:56 2012 from 10.13.90.129
 
[xxx@xxx000 ~]
$uptime
12:35:02 up 34 days, 13:57,  2 users,  load average: 0.12, 0.19, 0.18
 
[xxx@xxx000 ~]
$
[xxx@xxx001 ~]
$

其实在python可以实现相同功能(上次有同学问python怎么自动完成交互),那我把上面程序修改成python版本

例一:pexpect module

#!/usr/bin/env python
 
import pexpect
import os
import traceback
 
#user:ssh usrename
#host:ssh hostname
#password:ssh hostname's password
#command:ssh hostname's command
def ssh_command (user, host, password, command):
    '''The command will run on remote host'''
    ssh_newkey = 'Are you sure you want to continue connecting'
    #fork child process
    child = pexpect.spawn('ssh -l %s %s %s' % (user, host, command))
    i = child.expect([pexpect.TIMEOUT, ssh_newkey, '(?i)password: '],timeout=2)
    if i == 0: # Timeout
       print 'ERROR1'
       print 'SSH could not login. Here is what SSH said:'
       #print child.before, child.after
       return None
    if i == 1: # SSH does not have the public key. Just accept it.
       child.sendline ('yes')
       child.expect ('(?i)password: ')
       i = child.expect([pexpect.TIMEOUT, '(?i)password: '],timeout=2)
       if i == 0: # Timeout
          print 'ERROR2'
          print 'SSH could not login. Here is what SSH said:'
          print child.before, child.after
          return None
    child.sendline(password)
    return child
 
def main ():
    host = 'xxx000'
    user = 'yourusername'
    #you can import getpass module to protect your password
    password = 'yourpassword'
    command = 'uptime'
    child = ssh_command (user, host, password, command)
    child.expect(pexpect.EOF)
    print child.before
 
if __name__ == '__main__':
    try:
        main()
    except Exception, e:
        print str(e)
        traceback.print_exc()
        os._exit(1)
[xxx@xxx001 ~]
$python ssh.py
 
10:25:13 up 35 days, 11:47,  1 user,  load average: 0.30, 0.43, 0.37

注意:有些同学在网上问,执行过程报如下错误,怎么解决:我是写一个很简单python脚本,远程登陆目标主机后,再执行ssh.py就不报错了

$python ssh.py
ERROR1
SSH could not login. Here is what SSH said:
Password:  <class 'pexpect.TIMEOUT'>
'NoneType' object has no attribute 'expect'
Traceback (most recent call last):
  File "ssh.py", line 45, in <module>
    main()
  File "ssh.py", line 40, in main
    child.expect(pexpect.EOF)
AttributeError: 'NoneType' object has no attribute 'expect'

例二:pxssh module

import pxssh  
try: 
    s = pxssh.pxssh() 
    hostname = 'xxx000'  
    username = 'yourusername'
    password = 'yourpassword'
    s.login (hostname, username, password)  
    s.sendline ('uptime')  
    s.prompt() 
    print s.before 
    s.logout() 
except pxssh.ExceptionPxssh, e:  
    print "pxssh failed on login." 
    print str(e)
[xxx@xxx001 ~]
$python ssh.py
uptime
 10:47:06 up 35 days, 12:09,  3 users,  load average: 0.21, 0.36, 0.36

使用pexpect或pxssh可以很方便和远程主机进行自动交互,当然这两个module还有许多属性及方法,如果需要更详细了解,可以参考以下三篇文章

http://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/index.html
http://www.ibm.com/developerworks/cn/linux/l-cn-pexpect2/
http://www.noah.org/wiki/Pexpect#Q:_Isn.27t_there_already_a_Python_Expect.3F

One Response to “pexpect介绍”

  1. […] pssh、pexpect在以文章有介绍,这次介绍一下rpyc,就像rpyc文档介绍一下,rpyc支持远程调用、分布式计算,以较少代码量实现需复杂socket编程,但个人觉得rpyc认证方式有点鬼。 以代码方式介绍: […]

Post a Comment