Python Pexpect库实现SSH与SFTP自动化交互详解
本文详细介绍Python中Pexpect库的使用方法,重点演示如何通过该库实现SSH远程命令执行及SFTP文件传输的自动化交互。文章涵盖环境配置、代码示例及SFTP操作中关键的期望匹配注意事项,帮助开发者解决远程服务器自动运维与测试中的交互问题。
简介
近期工作中需要远程连接服务器并执行其中的Python脚本,经过调研发现Pexpect库是解决此类问题的有效工具,特此记录相关使用心得。
Pexpect是一个用于生成子应用程序并控制其交互的Python模块。它能够通过期望模式(expect pattern)对子应用的输出做出响应,模拟人类输入命令的行为,从而实现对子应用的控制。
该库主要应用于需要自动交互的场景,例如SSH、SFTP、PASSWD和TELNET等协议的操作。此外,它还可用于编写自动设置脚本,为多台服务器重复安装软件包,或应用于自动化的软件测试流程中。
需要注意的是,Pexpect的核心功能依赖于Python的基本库pty,而pty库仅在类Unix系统环境下可用,这意味着该工具在Windows原生环境中可能无法直接使用。
Pexpect关于SSH的使用
注:为便于测试,本例直接使用虚拟机通过SSH连接本机。
环境
1. Win10 物理机 2. Vmware Centos 虚拟机 3. Xshell 4. 在虚拟机中安装pexpect库:pip install pexpect
在虚拟机中创建一个Python文件
#-*- coding:UTF-8 -*-
import pexpect
# 定义ssh连接
def ssh(user,host,password,command):
#创建子应用,命令是 ssh -l root 127.0.0.1 python /home/python/test.py
child = pexpect.spawn('ssh -l %s %s %s'%(user,host,command))
# 期待开启的子程序的显示,子程序的不同显示会匹配到不同key然后我们定义不同的操作
# 0 : 连接超时
# 1 :ssh有时候提示你是否确认连接
# 2 :提示输入密码
# 3 :匹配到#号,表示命令已经执行完毕。没用到
i = child.expect([pexpect.TIMEOUT, 'Are you sure you want to continue connecting','password:',r"([^-]>|#)"])
# 如果登录超时,renturn none
if i == 0: # Timeout
print "Timeout"
return None
# 提示是否确认连接
if i == 1:
child.sendline ('yes') # 我们输入yes
child.expect ('password: ')# 输入yes后 子程序应该提示输入密码,我们再次期待password
i = child.expect([pexpect.TIMEOUT, 'password: '])
#超时
if i == 0: # Timeout
return None
# 不考虑其他情况,走到此处时,要么timeout 已经return ,要么等待输入密码
#输入密码
child.sendline(password)
# 返回子程序
return child
if __name__ =='__main__':
try:
# 配置数据
host='127.0.0.1'
user="root"
password = '********'
command = 'python /home/python/test.py'
#command="ls -l"
child = ssh(user,host,password,command)
#这句是将子程序的命令行拉到末端
test = child.expect(pexpect.EOF)
#child中before就是我们要的数据,有时候还会在 after中
print child.before
print child.after
except Exception,e:
print str(e)
# 最终的显示结果是 test.py中打印的hahaha结果,
[root@localhost python]# python test_pexpect.py
hahaha
<class 'pexpect.exceptions.EOF'>
我们尝试一下开两个虚拟机的情况
上面的代码只需要更改ip user password即可
# ip 192.168.233.133 # user root # 在另一台虚拟机的相同位置创建/home/pyhton/test.py 内容如下 if __name__=="__main__": print "another virual machine hahaha" # 打印结果 [root@localhost python]# python test3.py another virual machine hahaha <class 'pexpect.exceptions.EOF'>
Pexpect 关于 SFTP的使用
与SSH类似,SFTP的操作逻辑是在当前机器上通过Python调用sftp命令连接远程IP,期望获取响应后输入密码,最后发送get命令以下载文件。
注:在实际使用时发现一个关键点:在每次执行sendline之前,都需要重新期望当前的sftp>提示符;或者在每次输入sendline之后重新期望sftp>。也就是说,必须期望匹配到该行,否则后续输入的命令均无反应。我的理解是,当远程连接的服务器有输出时,当前光标位置可能不在sftp>处,因此在sendline发送的内容将变得无意义。如果这个解释不对,望高人指点。
# --*-- coding:utf-8 --*--
import pexpect
import os
import time
def sftp(ip , password , command):
# 创建子应用
child = pexpect.spawn("sftp %s"%(ip))
i = child.expect([pexpect.TIMEOUT,'password:'])
# 超时
if i == 0 :
print "Timeout"
return None
# 准备输入密码
if i == 1 :
# 输入密码
child.sendline(password)
j = child.expect([pexpect.TIMEOUT,'sftp>'])
# 超时
if j == 0:
print "Timeout"
return None
# 匹配到进入sftp命令模式
if j==1:
print 'Before sftp get command'
print child.before
print "-----------------"
#发送命令
child.sendline(command)
child.expect(['sftp>'])
print "After sftp get command"
print child.before
print "-----------------"
child.sendline("bye")
#child.expect(['sftp>'])
print "After sftp bye"
print child.before
print "-----------------"
print child.after
return child
if __name__=='__main__':
ip = "192.168.233.133"
command = "get /home/python/test.txt"
password = "********"
child = sftp(ip , password , command)
print child.before
print child.after
if os.path.exists("./test.txt"):
print "Make sure transfer successfully"
else :
print "Can not find the transfer file"
# ----------------------------结果-----------------------------------------------
'''
Before sftp get command
Connected to 192.168.233.133.
-----------------
After sftp get command
get /home/python/test.txt
Fetching /home/python/test.txt to test.txt
/home/python/test.txt 100% 73 25.2KB/s 00:00
-----------------
After sftp bye
get /home/python/test.txt
Fetching /home/python/test.txt to test.txt
/home/python/test.txt 100% 73 25.2KB/s 00:00
-----------------
sftp>
get /home/python/test.txt
Fetching /home/python/test.txt to test.txt
/home/python/test.txt 100% 73 25.2KB/s 00:00
sftp>
Make sure transfer successfully
'''
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









