- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python pexpect模块及shell脚本except原理解析由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
expect脚本 。
expect是什么 。
expect是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预。说白了,expect就是一套用来实现自动交互功能的软件.
在实际工作中,我们运行命令、脚本或程序时,这些命令、脚本或程序都需要从终端输入某些继续运行的指令,而这些输入都需要人为的手工进行。而利用expect,则可以根据程序的提示,模拟标准输入提供给程序,从而实现自动化交互执行 。
由于在linux中的一些命令不太适合于脚本的自动化运行,比如fdisk,telnet,ftp连接下载等,所以必须使用except来解决交换问题.
except基础 。
包含以下四个命令 。
。
命令 | 作用 |
---|---|
send | 用于向进程发送字符串 |
except | 从进程接收字符串 |
spwan | 启动新进程 |
interact | 允许用户交互 |
。
代码举例 。
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/expect
set
timeout
30
set
host
"101.200.241.109"
set
username
"root"
set
password
"123456"
spawn ssh $username@$host
expect
"*password*"
{send
"$password\r"
}
interact
|
这是一段非常简单代码,演示了基本用法 。
#!/usr/bin/expect:使用expect来解释该脚本; 。
set timeout 30:设置超时时间,单位为秒,默认情况下是10秒; 。
set host "101.200.241.109":设置变量; 。
spawn ssh $username@$host:spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。它主要的功能是给ssh运行进程加个壳,用来传递交互指令; 。
expect "password":这里的expect也是expect的一个内部命令,这个命令的意思是判断上次输出结果里是否包含“password”的字符串,如果有则立即返回;否则就等待一段时间后返回,这里等待时长就是前面设置的30秒; 。
send "$password\r":当匹配到对应的输出结果时,就发送密码到打开的ssh进程,执行交互动作; 。
interact:执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上.
这就是对上述这段简单简单脚本的分析,在上述的示例中,涉及到expect中一个非常重要的概念——模式-动作;即上述expect "password" {send "$password\r"}这句代码表达出来的含义.
模式-动作 。
结合着expect "password" {send "$password\r"}这句代码来说说“模式-动作”。简单的说就是匹配到一个模式,就执行对应的动作;匹配到password字符串,就输入密码 。
如下所示:
1
2
3
4
5
6
7
8
9
10
|
expect {
"password"
{
send
"$password\r"
exp_continue
}
eof
{
send
"eof"
}
}
|
其中exp_continue表示循环式匹配,通常匹配之后都会退出语句,但如果有exp_continue则可以不断循环匹配,输入多条命令,简化写法.
传参 。
很多时候,我们需要传递参数到脚本中,现在通过下面这段代码来看看如何在expect中使用参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#!/usr/bin/expect
if
{$argc <
3
} {
puts
"Usage:cmd <host> <username> <password>"
exit
1
}
set
timeout
-
1
set
host [lindex $argv
0
]
set
username [lindex $argv
1
]
set
password [lindex $argv
2
]
spawn ssh $username@$host
expect
"*password*"
{send
"$password\r"
}
interact
|
在expect中,\$argc表示参数个数,而参数值存放在$argv中,比如取第一个参数就是[lindex $argv 0],以此类推.
FTP下载expect脚本 。
使用yum安装expect 。
yum install expect 。
按照如下编写expect脚本 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/bin/expect -f
set
ip [lindex $argv
0
]
#脚本的第一个参数,远程主机的IP地址
set
file
[lindex $argv
1
]
#脚本的第二个参数,指定下载的文件名
set
timeout
10
#设置超时时间10秒
spawn ftp $ip
#运行ftp $ip命令
expect
"Name*"
#如果出现Name字符
send
"anonymous \r"
#则输入anoymous(匿名用户)并回车
expect
"Password:*"
#如果出现Password字符
send
"\r"
#则仅输入回车
expect
"ftp>*"
#如果出现ftp>字符
send
"get $file\r"
#则发送get $file命令
expect {
"*Failed*"
{ send_user
" Download failed\r"
;send
"quit\r"
}
#如果返回的字符串有Failed,则说明下载失败,send_user回显信息 Download failed
"*send*"
{ send_user
" Download ok\r"
;send
"quit\r"
}
#如果返回的字符串有send,则说明下载失败,send_user回显信息 Download ok
}
expect eof
#结束循环匹配
|
给脚本加上可执行权限chmod +x expect_ftp_auto.exp 。
pexpect模块 。
pexpect可以理解为linux下的expect的python封装,通过pexpect可以实现ssh,ftp,passwd,telnet等命令的进行自动交互 。
安装pip install pexpect 。
简单实现ssh自动登录的示例如下:
1
2
3
4
5
|
import
pexpect
child
=
pexpect.spwan(
'scp foo user#expample.com:.'
) #spwan启动scp程序
child.expect(
'Password:'
)
#expect方法等待子程序产生的输出,判断是否匹配定义的字符串
#‘Password:'
child.sendline(mypassword)
#匹配后则发送密码进行回应
|
核心组件 。
spawn类 。
spawn是pexpect的主要入口,功能是启动和控制子应用程序,以下是它的构造函数 。
class pexpect.spwan(command,args=[],timeout=30,maxread=2000,searchwindowsize=None,logfile=None,cwd=None,env=None,ignore_sighup=True) 。
其中,command参数可以是任意已知的系统命令,比如 。
child=pexpect.spawn('user/bin/ftp') 。
当子程序需要参数的时候,还可以使用python列表来代替参数,如 。
child = pexpect.spwan('user/bin/ssh user@example.com') 。
参数timeout为等待结果的超时时间,maxread为从终端控制台一次读取的最大字节数,searchwindowsize参数为匹配的缓冲区字符串的位置,默认是从开始位置匹配 。
需要注意的是,pexpext不会解析shell命令中的元字符,包括重定向> 管道|或者通配符,此时可以将三个特殊元字符的命令作为/bin/bash的参数进行调用 。
child =expect.spwan('/bin/bash -c "ls -l | grep LOG> logs.txt"') child.expect(pexpect.EOF) 。
可以通过将命令的参数以PYTHON列表的方式进行替换,从而使得语法更加清晰,下面的代码等同于上面的代码 。
shell_cmd='ls -l | grep LOG >logs.txt' child=pexpext.spwan('/bin/bash',['-c,shell_cmd]) child.expect(pexpect.EOF) 。
在调试代码时,希望获取pexpect的输入与输出信息,以便了解匹配的情况,一种时写到日志中,另一种时输出到标准输出 。
写到日志中 。
chidl-pexpect.spwan('some_command') fout=file('mylog.txt,'w') child.logfile=fout 。
输出到标准输出的方法 。
child=pexpect.swpan('some_command') chuld.logfile=sys.stdout 。
以下为SSH远程登录举例,登录成功后显示/home目录的文件并且记录输入与输出 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
pexpect
import
sys
child
=
pexpect.spawn(
'ssh root@172.31.208.129'
)
fout
=
open
(
'mylog.txt'
,
'w'
)
child.logfile
=
fout
#child.logfile=sys.stdout
child.expect(
'password:'
)
child.sendline(
'abc@123'
)
child.expect(
'#'
)
child.sendline(
'ls /home'
)
child.expect(
'#'
)
|
expect方法 。
expect定义了子程序输出的匹配规则 。
方法定义:expect(pattern,timeout=-1,searchwindowsize=-1) 。
其中,参数pattern表示字符串,pexpext.EOF(指向缓冲区,无匹配项)、pexpect,TIMEOUT(匹配等待超时),正则表达式或者列表 。
参数timeout指定了等待匹配结果的超时时间,单位为秒,当超时被触发的时候,expect将匹配到pexpext.TIMEOUT,参数searchwindowsize为匹配的缓冲字符串的位置,默认时从开始的位置匹配 。
read相关方法 。
下面的的方法作用都是向子程序发送响应命令 。
send(self,s) #发送命令,不回车 sendline(self,s=' '),#发送命令,回车 snedcontrol(self.char) #发送控制字符 sendeof() #发送eof 。
run函数 。
run时使用pexpext进行封装的调用外部命令的的函数 。
from pexpect import * run('scp foo user@example.com:.',events={'(?i)password':mypassword]) 。
pxssh类 。
针对ssh会话操作上再做一次封装 。
class pexpext.pxssh.pxssh(timeout=30,maxread=2000,searchwindwosize=None,logfile=None,cwd=None,env=None) 。
常用方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import
pxssh
import
getpass
try
:
s
=
pxssh.pxssh()
#创建对象s
hostname
=
raw_input
(
'hostname: '
)
username
=
raw_input
(
'username: '
)
password
=
getpass.getpass(
'password: '
)
#接收密码输入
s.login (hostname, username, password)
#建立ssh连接
s.sendline (
'uptime'
)
# 运行uptime命令
s.prompt()
# 匹配系统提示符
print
s.before
# 打印系统体术符号出现前的命令输出
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)
|
FTP自动操作 。
实现自动交互登录FTP操作 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import
pexpect
import
sys
child
=
pexpect.spawnu(
'ftp ftp.openbsd.org'
)
#运行ftp命令
child.expect(
'(?i)name .*: '
)
#(?!)表示后面的字符串正则表达式忽略大小写
child.sendline(
'anonymous'
)
# 输入ftp账号信息
child.expect(
'(?i)password'
)
#匹配密码提示
child.sendline(
'pexpect@sourceforge.net'
)
child.expect(
'ftp> '
)
child.sendline(
'bin'
)
#启用二进制传输
child.expect(
'ftp> '
)
child.sendline(
'get robots.txt'
)
child.expect(
'ftp> '
)
sys.stdout.write (child.before)
#输出匹配的"ftp"之前的输入与输出操作
print
(
"Escape character is '^]'.\n"
)
sys.stdout.write (child.after)
sys.stdout.flush()
child.interact()
# Escape character defaults to ^] #让出控制权,用户可以继续当前会话手工控制子程序,默认输入"^]"字符跳出
child.sendline(
'bye'
)
child.close()
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://blog.51cto.com/11555417/2514325 。
最后此篇关于Python pexpect模块及shell脚本except原理解析的文章就讲到这里了,如果你想了解更多关于Python pexpect模块及shell脚本except原理解析的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我对ansible非常陌生,我正在尝试运行一个剧本来更改主机的root密码,所以我使用pexpect模块的expect命令。我成功地在主机和运行 playbook 的本地服务器上安装了带有 pytho
我对 python 非常陌生,我有一个简单的问题我有这个功能 def testU(self): b = pexpect.spawn('users') b.expect(
是否可以同时“等待”来自 expect 命令的不同答案? 例如:child.expect('first', 'second') 如果是,如何区分是哪个触发了它? 最佳答案 是的,你可以这样做: i =
我正在尝试编写一个程序来运行一些带有模拟用户数据的 shell 命令。 问题在于,如果代码末尾没有这一行,shell 命令将无法正确运行: raw_input('press to exit') 我怎
我想连接到运行 CLISH 的服务器,在给出密码提示时提供密码(有效),然后发出“shell”命令将我跳转到 bash shell(有效),然后测试是否存在如果文件丢失则打印“true”,如果存在(有
我正在 CentOS 上自动执行几个配置步骤。为此,我还需要重新启动系统。我正在通过 python pexepct 调用“重启”命令,但是我需要等到系统启动才能执行剩余的脚本。为此,我编写了这段小代码
我是Python新手,我正在尝试使用pexpect,对interact的输入/输出过滤器感兴趣。但我不知道如何使用过滤器。 在Pexpect的文档中,关于交互方法,提到: interact(escap
我只是想设置一个脚本来从基于 unix 的设备中检索一些输出,在这里你可以找到我的代码: import pexpect import time,sys, traceback, os telconn =
我正在使用 python 的 pexpect 模块来自动执行任务,我需要帮助来找出与 sendcontrol 一起使用的关键字符。如何发送控制键 ENTER ?为了将来引用,我们如何找到关键人物? 这
我试图在从未知状态恢复后清除行中的任何字符,因为在某些情况下它们包含提示和我在未来 expect 方法调用中使用的其他关键字。我尝试了多种方法,结果好坏参半,因为我不断遇到非预期的行为。 看到意外行为
我正在使用 python pexpect 编写脚本以在远程计算机上执行另一个脚本。它在正常情况下工作正常,但如果远程脚本中有 time.sleep,它会失败。 我想到达远程机器,在后台启动脚本然后退出
背景介绍 Expect 程序主要用于人机对话的模拟,就是那种系统提问,人来回答 yes/no ,或者账号登录输入用户名和密码等等的情况。因为这种情况特别多而且繁琐,所以很多语言都有各种自己的实现。
我正在使用pexpect.py脚本登录并获取主机名信息。 基本上我是这样运行的 ~$:./pexpect.py -h{hostname} -u{user} -p{password} 您将在下面看到,它
在下面的代码片段中,如何找到make的退出代码?具体来说,我需要知道 make 是否失败或成功。感谢您提供任何意见。 process = pexpect.spawn("/bin/bash") proc
我正在使用pexpect命令学习python,试图将usign ssh脚本编写到多个服务器并运行远程安装,但是当脚本运行到child.expect('$')时,它超时了,并且没有执行后续任务,可以看看
我正在浏览 pexpect 文档,它说您可以调用 run() 函数来执行命令并返回输出 所以我执行了以下操作,但出现错误。我在这里错过了什么吗? >>> pexpect.run('pwd') '/ho
我们的“共享”服务器上有一些奇怪的设置,在某些情况下不会记住我的 git 密码。我努力解决真正的问题;但在某个时候我放弃了并创建了这个 python 脚本: #!/usr/bin/env python
我正在尝试编写非常简单的程序,使用 pexpect 控制远程计算机。但远程系统不会对发送的命令使用react。 这是源代码: #!/usr/bin/env python3 # -*- coding:
我想 ssh 到网络上的另一个节点作为更大的 python 脚本的一部分,我正在使用 pexpect,当我执行以下操作时它可以工作: session=spawn('ssh root@172.16.21
我正在稳步研究如何通过运行命令来 ssh 和解析设备上的数据。在这一努力的过程中,我遇到了一些问题,并且我提出的问题得到了很多帮助。我现在正在使用 pexpect,但我在文档中没有看到太多与我正在做的
我是一名优秀的程序员,十分优秀!