python python的pexpect模块 模块

pexpect模块
由 匿名 (未验证)
  pexpect用来启动子程序,使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的python模块,当然我们可以使用他来做ssh登陆,ssh模块登陆还有一个基于python实现远程连接,用于ssh远程执行命令,文件传输等功能的ssh客户端模块paramiko。
  在开发时也经常会使用pexpect模块,所以这里简单介绍一下pexpect。
  run():直接执行命令返回结果和状态
  run里有一个command参数,可以直接写命令然后拿到命令返回的状态和结果。
In [2]: import pexpect
In [3]: pexpect.run("ls /tmp/")
  我的/tmp下的东西有点多,已经删除了部分,此时只拿到了执行的结果但是没有拿到执行的状态。
In [4]: pexpect.run("ls /tmp", withexitstatus=1)
  withexitstatus为1则表示需要返回执行状态,默认不返回。
  执行状态为:
  返回的结果是一个元组,下标1的值为0即执行成功,非0则为执行失败。
  命令不存在时会报错,
  命令存在但是执行失败则打印错误信息,得到非0状态码。
  启动子程序,有丰富的方法实现对子程序的控制。
  比如我们使用spawn进行ssh连接:
In [7]: ssh_aliyun = pexpect.spawn('ssh 120.79.254.225')
In [8]: ssh_aliyun.expect("password:")
  生成一个实例对象,使用在expect期望的结果中我们可以使用完全匹配也可以使用正则匹配。
  当匹配成功以后会返回状态码0,匹配字段不存在,则程序阻塞,知道timeout程序会报错。
  注:expect中的$就是$不是正则表达式里的以某某结尾的意思。
  当然我们不希望匹配不成功而导致程序崩溃,expect中也可以填入错误状态,或者多个期待值,放在一个列表中。
In [18]: ssh_aliyun = pexpect.spawn('ssh 120.79.254.225')
In [19]: ssh_aliyun.expect([pexpect.TIMEOUT, pexpect.EOF, "password:"])
Out[19]: 2
  返回的结果为列表下标索引值。timeout则结果为0.
  对于刚才的实例,我对阿里云服务器发起ssh远程连接,需要进行密码校验,那么我们如何进行命令键入呢。
  我们可以使用send(),sendline(),sendcontrol(char)。向子程序发送指令。前两种就是发送指令,后一种发送控制符(比如发送ctrl+c中断命令)。
  密码登陆的ssh脚本
import pexpect
def login_ssh_passwd(port="",user="",host="",passwd=""):
'''函数:用于实现pexepect实现ssh的自动化用户密码登录'''
# print 'ssh -p %s %s@%s' % (port,user, host)
port and user and host and passwd:
ssh = pexpect.spawn('ssh -p %s %s@%s' % (port,user, host))
i = ssh.expect(['password:', 'continue connecting (yes/no)?'], timeout=5)
if i == 0 :
ssh.sendline(passwd)
elif i == 1:
ssh.sendline('yes\n')
ssh.expect('password: ')
ssh.sendline(passwd)
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
if index == 0:
print("logging in as root!")
#终端直接接管子程序会话,在终端直接操控ssh
# ssh.interact()
elif index == 1:
print("logging process exit!")
elif index == 2:
print("logging timeout exit")
print("Parameter error!")
  通过密钥方式登陆
def login_ssh_key(keyfile="",user="",host="",port=""):
'''函数:用于实现pexepect实现ssh的自动化密钥登录'''
port and user and host and keyfile:
ssh = pexpect.spawn('ssh -i %s -p %s %s@%s' % (keyfile,port,user, host))
i = ssh.expect( [pexpect.TIMEOUT,'continue connecting (yes/no)?'], timeout=2)
# print '...................................',0
if i == 1:
ssh.sendline('yes\n')
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
index = ssh.expect (["#", pexpect.EOF, pexpect.TIMEOUT])
if index == 0:
print("logging in as root!")
ssh.interact()
elif index == 1:
print("logging process exit!")
elif index == 2:
print("logging timeout exit")
print("Parameter error!")
  使用pexpect实现ssh远程登陆存在一些问题,依赖终端来完成登陆。在不同的登陆环境(系统不一致,端口不一致等)兼容性比较差。
  在资产管理的登陆扫描探测的具体环境中不适合直接使用pexpect来操作。
添加新评论pexpect是python交互模块,有两种使用方法,一种是函数:run另外一种是spawn类
1.pexpect& module 安装&
  pexpect属于第三方的,所以需要安装,
&&&&& 目前的版本是 3.3 下载地址
  安装步骤:  
pexpect-3.3.tar.gz
cd pexpect-3.3
python setup install (require root)
但是 这个安装需要root权限,如果没有root权限在,还能使用吗?
  答案是肯定的,你只需要把lib的路径放入sys.path。这样便可以使用pexpect
#!/usr/bin/env python
import sys
sys.path.append('pexpect-3.3/build/lib')
  确认安装成功:
&&& import pexpect
&&& dir(pexpect)
['EOF', 'ExceptionPexpect', 'PY3', 'TIMEOUT', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__revision__', '__version__', '_run', 'codecs', 'errno', 'fcntl', 'is_executable_file', 'os', 'pty', 're', 'resource', 'run', 'runu', 'searcher_re', 'searcher_string', 'select', 'signal', 'spawn', 'spawnu', 'split_command_line', 'stat', 'struct', 'sys', 'termios', 'time', 'traceback', 'tty', 'types', 'which']
2.使用方法
  run 函数,run函数和os。system()差不多,所不同的是os.system返回的是整数,而run返回字符串
&&& print pexpect.run('ping localhost -c 3')
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.088 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.088 ms
--- localhost ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.087/0.087/0.088/0.010 ms
&spawn 类是通过生成子程序sendline发送命令与expect拿回返回进行交互
import pexpectchild = pexpect.spawn('python',timeout=3)child.expect("&&&")child.sendline("exit()")print child.before&& # Print the result of the ls command.
timeout是等待时间,如果超过就会抛出exception,可以 使用except关键字捕获
fout=file('filename','a') #w write /a appendchild = pexpect.spawn('su root')
child.logfile = sys.stdoutchild.logfile_send=fout
#!/usr/bin/python
this script can batch add user
everytime will add specific usename
user mumber and password
create by Young
require pexpect module, if you don't have one
please install this module
if you can't install this module please
this module path to sys.path
import pexpect
import getopt
import sys
import random
import string
# usage fuction
def usage():
Usage: python %s
--name user --amount 100 --password [optional]
or python %s
-n user -a 100 -p [optional]
this will create user1~user100 and default password will be random or specific.
make sure when you run this script as root
the username you want create
-a,--amount
the amount of users you want create
-p,--password
the default password of use your create
display this help and exit
-v,--version
output version information and exit
%(sys.argv[0],sys.argv[0])
# get the parameters
# set the default user name
user_name='user'
# generate random password
def set_password():
word=[x for x in 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ']
p=string.join(random.sample(word, 8)).replace(" ","")
# number of users ,set default users number as 10
number_of_users=10
password=set_password()
is_ramdom_password=True
#print password
def get_command():
opts, args = getopt.getopt(sys.argv[1:], "n:a:p:hv", ["name=","amount=","password=","help", "version"])
except getopt.GetoptError as err:
# print help information and exit
print str(err) # will print something like "option -a not recognized"
sys.exit(2)
#print opts,args
for option,value in opts:
#print "-----------&"+option+' &&&&'+value
if option in ["-n","--name"]:
if(len(value)&=4):
global user_name
user_name=value
print "invaild usename,will use user"
elif option in ["-a","--amount"]:
if value.isdigit():
if( int(str(value))&0 and int(str(value))& 1000 ):
global number_of_users
number_of_users=int(str(value))
sys.exit(2)
print "ValueError: invalid literal for ",value
print "invaild amount,will use defualt"
elif option in ["-p","--password"]:
if(len(value)&=6):
global password
password=value
global is_ramdom_password
is_ramdom_password=False
print "invaild password,will use random"
elif option in ["-v","--version"]:
print sys.argv[0]+' 1.0.0'
sys.exit(0)
elif option in ("-h", "--help"):
sys.exit(0)
assert False, "unhandled option"
sys.exit(2)
def check_root():
if( os.environ['USER']!='root'):
print 'Permission denied,please su root'
sys.exit()
#use pexpect to adduser
def run_add(user,mypassword):
log = file('adduser.log','a')
flag=os.system('adduser '+user)
if(flag!=0):
os.system('userdel '+user)
os.system('adduser '+user)
child=pexpect.spawn('passwd '+user,timeout=5)
child.logfile = log
child.logfile_send=sys.stdout
child.expect("New password:")
child.sendline(mypassword)
child.expect("Retype new password:")
child.sendline(mypassword)
child.expect("passwd: all authentication tokens updated successfully.")
except pexpect.EOF:
except pexpect.TIMEOUT:
def add_user(name,amount,password,is_ramdom_password):
check_root()
for number in range(1,amount+1):
if(is_ramdom_password):
print "%4d: adduser %s%-4d password %s " %(number,name,number,set_password())
run_add(name+str(number),set_password())
print "%4d: adduser %s%-4d password %s " %(number,name,number,password)
run_add(name+str(number),set_password)
get_command()
add_user(user_name,number_of_users,password,is_ramdom_password)
阅读(...) 评论()后使用快捷导航没有帐号?
查看: 1418|回复: 0
探索 Pexpect,第 1 部分:剖析 Pexpect
注册会员, 积分 91, 距离下一级还需 109 积分
论坛徽章:1
探索 Pexpect,第 1 部分:剖析 Pexpect
Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块。 Pexpect 可以用来和像 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。本文章介绍 Pexpect 的主要用法和在实际应用中的注意点。 Python 语言的爱好者,系统管理人员,部署及测试人员都能使用 Pexpect 在自己的工作中实现与命令行交互的自动化。2
(), 软件工程师, IBM (), 软件开发工程师, IBM (), 软件工程师, IBM2009 年 5 月 07 日内容
概述Pexpect 是 Don Libes 的 的 一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块。 Pexpect 的使用范围很广,可以用来实现与 ssh、ftp 、telnet 等程序的自动交互;可以用来自动复制软件安装包并在不同机器自动安装;还可以用来实现软件测试中与命令行交互的自动化。下载Pexpect 可以从
网站。 本文介绍的示例使用的是 2.3 版本,如不说明测试环境,默认运行操作系统为 fedora 9 并使用 Python 2.5 。安装 download pexpect-2.3.tar.gz&&tar zxvf pexpect-2.3.tar.g&&cd pexpect-2.3&&python setup.py install&&(do this as root)
依赖Python 版本 2.4 或者 2.5pty module ,pty 是任何 Posix 系统标准库的一部分
由于其依赖 pty module ,所以 Pexpect 还不能在 Windows 的标准 python 环境中执行,如果想在 Windows 平台使用,可以使用在 Windows 中运行 Cygwin 做为替代方案。遵循 MIT 许可证根据 Wiki 对 MIT License 的介绍“该模块被授权人有权利使用、复制、修改、合并、出版发行、散布、再授权及贩售软件及软件的副本。被授权人可根据程序的需要修改授权条款为适当的内容。在软件和软件的所有副本中都必须包含版权声明和许可声明。”Pexpect 提供的 run() 函数:清单 1. run() 的定义run(command,timeout=-1,withexitstatus=False,events=None,\& & extra_args=None,logfile=None, cwd=None, env=None)
函数 run 可以用来运行命令,其作用与 Python os 模块中 system() 函数相似。run() 是通过 类实现的。如果命令的路径没有完全给出,则 run 会使用 which 命令尝试搜索命令的路径 。清单 2. 使用 run()执行 svn 命令from pexpect import * run (&svn ci -m 'automatic commit' my_file.py&)
与 os.system() 不同的是,使用 run() 可以方便地同时获得命令的输出结果与命令的退出状态 。清单 3. run() 的返回值from pexpect import *(command_output, exitstatus) = run ('ls -l /bin', withexitstatus=1)
command_out 中保存的就是 /bin 目录下的内容。Pexpect 提供的 spawn() 类:使用 Pexpect 启动子程序清单 4. spawn 的构造函数class spawn:& & def __init__(self,command,args=[],timeout=30,maxread=2000,\& & searchwindowsize=None, logfile=None, cwd=None, env=None)
spawn是Pexpect模块主要的类,用以实现启动子程序,它有丰富的方法与子程序交互从而实现用户对子程序的控制。它主要使用 pty.fork() 生成子进程,并调用 exec() 系列函数执行 command 参数的内容。可以这样使用:清单 5. spawn() 使用示例child = pexpect.spawn ('/usr/bin/ftp') #执行ftp客户端命令child = pexpect.spawn ('/usr/bin/ssh ') #使用ssh登录目标机器child = pexpect.spawn ('ls -latr /tmp') #显示 /tmp目录内容
当子程序需要参数时,还可以使用一个参数的列表:清单 6. 参数列表示例child = pexpect.spawn ('/usr/bin/ftp', [])child = pexpect.spawn ('/usr/bin/ssh', [''])child = pexpect.spawn ('ls', ['-latr', '/tmp'])
在构造函数中,maxread 属性指定了 Pexpect 对象试图从 tty 一次读取的较大字节数,它的默认值是2000字节 。由于需要实现不断匹配子程序输出, searchwindowsize 指定了从输入缓冲区中进行模式匹配的位置,默认从开始匹配。logfile 参数指定了 Pexpect 产生的日志的记录位置。例如:清单 7. 记录日志child = pexpect.spawn('some_command')fout = file('mylog.txt','w')child.logfile = fout
还可以将日志指向标准输出:清单 8. 将日志指向标准输出child = pexpect.spawn('some_command')child.logfile = sys.stdout
如果不需要记录向子程序输入的日志,只记录子程序的输出,可以使用:清单 9. 记录输出日志child = pexpect.spawn('some_command')child.logfile_send = sys.stdout
使用 Pexpect 控制子程序为了控制子程序,等待子程序产生特定输出,做出特定的响应,可以使用 expect 方法。清单 10. expect() 定义expect(self, pattern, timeout=-1, searchwindowsize=None)
在 参数中: pattern 可以是正则表达式, pexpect.EOF , pexpect.TIMEOUT ,或者由这些元素组成的列表。需要注意的是,当 pattern 的类型是一个列表时,且子程序输出结果中不止一个被匹配成功,则匹配返回的结果是缓冲区中最先出现的那个元素,或者是列表中最左边的元素。使用 timeout 可以指定等待结果的超时时间 ,该时间以秒为单位。当超过预订时间时, expect 匹配到pexpect.TIMEOUT。如果难以估算程序运行的时间,可以使用循环使其多次等待直至等待运行结束:清单 11. 使用循环while True:& & index = child.expect([&suc&,&fail&,pexpect.TIMEOUT])& &&&if index == 0:& && && &breakelif index == 1:& && &&&return Falseelif index == 2:& && &&&pass& && &&&#continue to wait
expect() 在执行中可能会抛出两种类型的异常分别是 EOF and TIMEOUF,其中 EOF 通常代表子程序的退出, TIMEOUT 代表在等待目标正则表达式中出现了超时。清单 12. 使用并捕获异常try:& & index = pexpect (['good', 'bad'])& && &&&if index == 0:& && && && &do_something()& && &&&elif index == 1:& && && && &do_something_else()& & except EOF:& && &&&do_some_other_thing()except TIMEOUT:& & do_something_completely_different()
此时可以将这两种异常放入expect等待的目标列表中:清单 13. 避免异常index = p.expect (['good', 'bad', pexpect.EOF, pexpect.TIMEOUT]) if index == 0:& &&&do_something()elif index == 1:& & do_something_else()elif index == 2:& & do_some_other_thing()elif index == 3:& & do_something_completely_different()
expect 不断从读入缓冲区中匹配目标正则表达式,当匹配结束时 pexpect 的 before 成员中保存了缓冲区中匹配成功处之前的内容, pexpect 的 after 成员保存的是缓冲区中与目标正则表达式相匹配的内容。清单 14. 打印 before 成员的内容child = pexpect.spawn('/bin/ls /') child.expect (pexpect.EOF) print child.before
此时 child.before 保存的就是在根目录下执行 ls 命令的结果。清单 15. send 系列函数send(self, s) sendline(self, s='') sendcontrol(self, char)
这些方法用来向子程序发送命令,模拟输入命令的行为。 与 send() 不同的是 sendline() 会额外输入一个回车符 ,更加适合用来模拟对子程序进行输入命令的操作。 当需要模拟发送 “Ctrl+c” 的行为时,还可以使用 sendcontrol() 发送控制字符。清单 16. 发送 ctrl+cchild.sendcontrol('c')
由于 send() 系列函数向子程序发送的命令会在终端显示,所以也会在子程序的输入缓冲区中出现,因此不建议使用 expect 匹配最近一次 sendline() 中包含的字符。否则可能会在造成不希望的匹配结果。清单 17. interact() 定义interact(self, escape_character = chr(29), input_filter = None, output_filter = None)
Pexpect还可以调用interact() 让出控制权,用户可以继续当前的会话控制子程序。用户可以敲入特定的退出字符跳出,其默认值为“^]” 。下面展示一个使用Pexpect和ftp交互的实例。清单 18. ftp 交互的实例:# This connects to the openbsd ftp site and# downloads the README file.import pexpectchild = pexpect.spawn ('ftp ftp.openbsd.org')child.expect ('Name .*: ')child.sendline ('anonymous')child.expect ('Password:')child.sendline ('')child.expect ('ftp& ')child.sendline ('cd pub/OpenBSD')child.expect('ftp& ')child.sendline ('get README')child.expect('ftp& ')child.sendline ('bye')
该程序与 ftp 做交互,登录到 ftp.openbsd.org ,当提述输入登录名称和密码时输入默认用户名和密码,当出现 “ftp&” 这一提示符时切换到 pub/OpenBSD 目录并下载 README 这一文件。以下实例是上述方法的综合应用,用来建立一个到远程服务器的 telnet 连接,并返回保存该连接的 pexpect 对象。清单 19. 登录函数:import re,sys,osfrom pexpect import *def telnet_login(server,user, passwd,shell_prompt= “#|-&”):& && &&&&& && &@summary: This logs the user into the given server.& & It uses the 'shell_prompt' to try to find the prompt right after login.& & When it finds the prompt it immediately tries to reset the prompt to '#UNIQUEPROMPT#'& & more easily matched.& && &@return: If Login successfully ,It will return a pexpect object& && &&&@raise exception: RuntimeError will be raised when the cmd telnet failed or the user& & and passwd do not match& && &@attention:1. shell_prompt should not include '$',on some server, after sendline& && && && && && &(passwd)& &the pexpect object will read a '$'.& && &2.sometimes the server's output before its shell prompt will contain '#' or& &&&'-&'&&So the caller should kindly assign the shell prompt& && &&&&& && &if not server or not user \& && && && &or not passwd or not shell_prompt:& && && & raise RuntimeError, &You entered empty parameter for telnet_login && && && && &child = pexpect.spawn('telnet %s' % server)& && &child.logfile_read = sys.stdout& && &index = child.expect (['(?i)login:', '(?i)username', '(?i)Unknown host'])& && &if index == 2:& && && & raise RuntimeError, 'unknown machine_name' + server& && &child.sendline (user)& && &child.expect ('(?i)password:')& && &child.logfile_read = None&&# To turn off log& & child.sendline (passwd)& && && && &while True:& && && & index = child.expect([pexpect.TIMEOUT,shell_prompt])& && && & child.logfile_read = sys.stdout& && && & if index == 0:& && && && &&&if re.search('an invalid login', child.before):& && && && && && &raise RuntimeError, 'You entered an invalid login name or password.'& && &&&elif index == 1:& && && && &&&break& && && & child.logfile_read = sys.stdout # To tun on log again& & child.sendline(“PS1=#UNIQUEPROMPT#”)& && &#This is very crucial to wait for PS1 has been modified successfully& && &#child.expect(“#UNIQUEPROMPT#”)& && &child.expect(&%s.+%s& % (“#UNIQUEPROMPT#”, “#UNIQUEPROMPT#”))& && &return child
Pxssh 类的使用:Pxssh 做为 pexpect 的派生类可以用来建立一个 ssh 连接,它相比其基类增加了如下方法:login() 建立到目标机器的ssh连接 ;losuckgout() 释放该连接 ;prompt() 等待提示符,通常用于等待命令执行结束。下面的示例连接到一个远程服务器,执行命令并打印命令执行结果。该程序首先接受用户输入用户名和密码,login 函数返回一个 pxssh 对象的链接,然后调用 sendline() 分别输入 “uptime”、“ls” 等命令并打印命令输出结果。清单 20. pxssh 示例import pxssh&&import getpass&&try: s = pxssh.pxssh()& &&&hostname = raw_input('hostname: ')& && &username = raw_input('username: ')& && &password = getpass.getpass('password: ')& && &s.login (hostname, username, password)& && &s.sendline ('uptime')&&# run a command& && &s.prompt()& && && && & # match the prompt& && &print s.before& && && &# print everything before the propt.& && &s.sendline ('ls -l')& && &s.prompt()& &&&print s.before& && &s.sendline ('df')& && &s.prompt()& &&&print s.before& && &s.logout() except pxssh.ExceptionPxssh, e:& && &print &pxssh failed on login.&& &&&print str(e)
Pexpect 使用中需要注意的问题:spawn() 参数的限制在 使用spawn执行命令时应该注意,Pexpect 并不与 shell 的元字符例如重定向符号 & 、&& 、管道 | ,还有通配符 * 等做交互,所以当想运行一个带有管道的命令时必须另外启动一个 shell ,为了使代码清晰,以下示例使用了参数列表例如:清单 21. 启动新的 shell 执行命令shell_cmd = 'ls -l | grep LOG & log_list.txt'child = pexpect.spawn('/bin/bash', ['-c', shell_cmd])child.expect(pexpect.EOF)
与线程共同工作Perl 也有 expect 的模块 , 但是 perl 的该模块在某些操作系统例如 fedora 9 或者 AIX 5 中不支持在线程中启动程序执行以下实例试图利用多线同时程登录到两台机器进行操作,不使用线程直接调用时 sub1() 函数可以正常工作,但是使用线程时在 fedora9 和 AIX 5 中都不能正常运行。清单 22. perl 使用 expect 由于线程和 expect 共同使用导致不能正常工作的程序 use E&&$timeout = 5;&&my $thr = threads-&create(\&sub1(first_server));&&my $thr2 = threads-&create(\&sub1(second_server));&&sub sub1&&{& && && & my $exp = new E& && && & $exp -& raw_pty(1);& && && & $exp -& spawn (&telnet&,$_[0]) or die &cannot access telnet&;& && &&&$exp -& expect ( $timeout, -re=&'[Ll]ogin:' );& && && & $exp -& send ( &user\n&);& && && & $exp -& expect ( $timeout, -re=&'[Pp]assword:' );& && && & $exp -& send ( &password\n& );& && && & $exp -& expect ( $timeout, -re=&& #& );& && && & $exp -& send ( &date\n& );& && && &$exp -& expect ( $timeout, -re=&'\w\w\w \w\w\w \d{1,2}& && && && && && && && && &\d\d:\d\d:\d\d \w\w\w \d\d\d\d');& && && & $localtime=$exp-&match();& && && &print &\tThe first server’s time is : $localtime\n&;& && && & $exp -& soft_close (); }&&print &This is the main thread!&;&&$thr-&join(); $thr2-&join();
Pexpect 则没有这样的问题,可以使用多线程并在线程中启动程序运行。但是在某些操作系统如 fedora9 中不可以在线程之间传递 Pexpect 对象。清单 使用 Pexpect 在线程中启动控制子程序应用实例:在实际系统管理员的任务中,有时需要同时管理多台机器,这个示例程序被用来自动编译并安装新的内核版本,并重启。它使用多线程,每个线程都建立一个到远程机器的 telnet 连接并执行相关命令。 该示例会使用上文中的。清单 23. 管理多台机器示例import sys,os&&from Login import * PROMPT = “#UNIQUEPROMPT#”class RefreshKernelThreadClass(threading.Thread):&&&&& The thread to downLoad the kernel and install it on a new server&&&&&& & def __init__(self,server_name,user,passwd):& && && & threading.Thread.__init__(self)& && && & self.server_name_ = server_name& && && & self.user_ = user& && && & self.passwd_ = passwd& && && & self.result_ = [] # the result information of the thread& && && && & def run(self):& && && & self.setName(self.server_name_) # set the name of thread& && && && && & try:& && && && && &#call the telnet_login to access the server through telnet& && && && && &child = telnet_login(self.server_name_,self.user_, self.passwd_)& && && & except RuntimeError,ex:& && && && &&&info = &telnet to machine %s failed with reason %s& % (self.server_name_, ex)self.result_.=(False, self.server_name_+info)& && && && & return self.result_& && && && && && &&&child.sendline(' cd ~/Download/dw_test && \& && && && &&&wget
&& \& && && && &&&tar zxvf -2.6.28.tar.gz && \& && && && && &cd linux-2.6.28 \& && && && &&&&& make mrproper && make allyesconfig and make -j 4 && make modules && \& && && && &&&make modules install && make install')& && && && && && &# wail these commands finish& && && &while True:& && && && &index = child.expect([PROMPT,pexpect.TIMEOUT,pexpect.EOF])& && && && &&&if index == 0:& && && && && && &break& && && && & elif index == 1:& && && && && &&&pass& && && && &elif index ==2 :& && && && && &&&self.result_=(False,'Sub process exit abnormally ')& && && && & return False& && && &# reboot the server& && &&&child.sendline('shutdown -Fr')& && && & child.expect('\r\n')& && && & retry_times = 10& && && &while retry_times & 0:& && && && && &index_shutdown = child.expect([&Unmounting the file systems&,& && && && && && && && && && && && && && &&&pexpect.EOF,& && && && && && && && && && && && && && && &pexpect.TIMEOUT])& && && && &&&if index_shutdown == 0 or index_shutdown == 1 :& && && && && && &break& && && && &&&elif index_shutdown == 2:& && && && && &&&retry_times = retry_times-1& && && && && &&&if retry_times == 0:& && && && && && && & self.result_=(False,'Cannot shutdown ')& && && && && && && & return self.result_& && && && && && && && && && && && &&&def refresh_kernel(linux_server_list,same_user,same_passwd):& && &&&&& && &@summary: The function is used to work on different linux servers to download& & the same version linux kernel, conpile them and reboot all these servers& && &To keep it simple we use the same user id and password on these servers& && &&&&&&& && &if not type(linux_server_list) == list:& && && &return (False,&Param %s Error!&%linux_server_list)& && && &&&if same_user is None or same_passwd is None or not& && &type(same_user)== str or not type(same_passwd) == str:& && && & return (False,&Param Error!&)& && && & thread_list = []& & # start threads to execute command on the remote servers& & for i in range (len(linux_server_list)):& && && & thread_list = RefreshKernelThreadClass(linux_server_list,& && && && && && && && && && && && && && && && &&&same_user,same_passwd)& && && &thread_list.start()& && && &# wait the threads finish& & for i in range (len(linux_server_list)):& && && & thread_list.join()& &&&# validate the result& & for i in range (len(linux_server_list)):& && && & if thread_list[0].result_[0] == False:& && && && &&&return False& && && &else:& && && && & return True&&if __name__ == &__main__&:& & refresh_kernel(server_list,&test_user&,&test_passwd&)
参考资料访问
的主页,了解更多 Expect 的内容。参考
上关于 MIT 许可证的介绍。查看文章介绍 Expect 在网络管理中的应用。 了解 Perl 语言中的 Expect 。在 寻找为 Linux 开发人员(包括 )准备的更多参考资料,查阅我们。在 developerWorks 上查阅所有 和 。
dataguru.cn All Right Reserved.
扫一扫加入本版微信群}

我要回帖

更多关于 python 安装模块 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信