通过python代码来实现类似expect shell的交互式能力,这样在python代码中能结合业务逻辑组装代码,具有比expect更强大的自动化处理能力。
import time
import paramiko
from paramiko import SSHClient, Channel
import re
recv_len = 1024 * 10
class PtySession(object):
def __init__(self, session, ending_char, timeout=10) -> None:
super().__init__()
self.session = session
self.last_line = ""
self.ending_char = ending_char
self.clear_tail()
self.timeout = timeout
def clear_tail(self):
清理输出还处于缓冲区中未读取的流
while True:
time.sleep(0.2)
if self.session.recv_ready():
self.last_line = self.session.recv(recv_len)
self.last_line = self.last_line.decode('utf-8')
print(self.last_line, end="")
if re.search(self.ending_char, self.last_line):
break
def destroy(self):
销毁并关闭session
:return:
:rtype:
self.clear_tail()
self.session.close()
def exp(self, *exp_cmds):
期望并执行,与expect的用法类似。
:param exp_cmds:
第一个元素为获取的期望结束字符,第二个元素为需要执行的命令,如果传入的第三个元素,则第三个元素必须为元祖,并且也同父级一样,属递归结构。
类似GNU的递归缩写。
:type exp_cmds: tuple
interval = 0.2
cur_time = 0.0
while True:
if self.session.recv_ready():
self.last_line = self.session.recv(recv_len).decode('utf-8')
print(self.last_line, end="")
elif self.session.send_ready():
for exp_cmd in exp_cmds:
_cmd = exp_cmd[1]
if not _cmd.endswith("\r"):
_cmd += "\r"
match = re.search(exp_cmd[0], self.last_line)
if match and match.group():
self.session.send(_cmd)
self.last_line = ""
if len(exp_cmd) == 3 and exp_cmd[2]:
self.exp(exp_cmd[2])
return
cur_time += interval
if cur_time >= self.timeout:
raise Exception("timeout...")
time.sleep(interval)
def send(self, cmd):
单纯的发送命令到目标服务器执行。
:param cmd: 命令
:type cmd: str
self.last_line = ""
if not cmd.endswith("\r"):
cmd += "\r"
self.session.send(cmd)
self.clear_tail()
if __name__ == '__main__':
====示例====
host = "127.0.0.1"
port = 22
username = "xxx"
pwd = "xxx"
_ssh_client = SSHClient()
_ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
_ssh_client.connect(hostname=host, timeout=60, port=port, username=username,
password=pwd)
print("ssh连接成功.")
_session = _ssh_client.get_transport().open_session(timeout=1 * 3600)
_session.get_pty()
_session.invoke_shell()
pty_session = PtySession(_session, ending_char=r"]\$ $", timeout=10)
pty_session.send("sleep 5\r")
pty_session.send("touch /test_a.txt")
pty_session.exp(
r"]\$ $",
"scp -P%s %s %s@%s:%s" % (
port,
"~/test_a.txt",
username,
host,
"~/test_b.txt"
下方exp的执行伪代码类似:
if(yes/no):
send yes
if (password):
send pwd
elif(passowrd):
send pwd
pty_session.exp(
"yes/no",
"yes",
(
("password", pwd)
("password", pwd)
pty_session.destroy()
该篇文章代码仅供参考。
后续有空再补结合SFTP自动化文件上传下载等通用处理封装。
需求说明通过python代码来实现类似expect shell的交互式能力,这样在python代码中能结合业务逻辑组装代码,具有比expect更强大的自动化处理能力。如果能通过该交互能力,结合SFTP来实现文件相关的操作,那就更加的强大了。该篇文章代码为交互式命令封装实现。实现依赖依赖paramiko库,所以需要执行pip install paramiko来安装。代码封装实现import timeimport paramikofrom paramiko import SSHClient
Pexpect是一个纯Python类似Expect的模块
Pexpect使Python成为控制其他应用程序的更好工具。
Pexpect是用于生成子应用程序的纯Python模块。 控制他们; 并响应其输出中的预期模式。 Pexpect的作品就像Don Libes的Expect。 Pexpect允许您的脚本生成子应用程序并对其进行控制,就像人类在键入命令一样。
Pexpect可用于自动化交互式应用程序,例如ssh,ftp,passwd,telnet等。它可用于自动化安装脚本,以在不同服务器上复制软件包安装。 它可以用于自动化软件测试。 Pexpect遵循Don Libes的Expect的精神,但Pexpect是纯Python。
Pexpect的主要功能需要Python标准库中的pty模块,该模块仅在类似Unix的系统上可用。 Windows中还提供了一些功能-等待来自文件描述符或子进程的
#!/usr/bin/python
import os,datetime
ip = iter(["1.1","1.2","1.3","1.4","1.5","1.6","1.7","1.8"])
port = iter(["3041","4227","2300","3212","2949","4502","3767","3405"])
passwd = iter(["1...
一、pexpect模块介绍
Pexpect使Python成为控制其他应用程序的更好工具。可以理解为Linux下的expect的Python封装,通过pexpect我们可以实现对ssh,ftp,passwd,telnet等命令行进行自动交互,而无需人工干涉来达到自动化的目的
二、Pexpect的安装
#python2
pip install pexpect
#python3
pip3 install pexpect
三、pexpect的核心组件
3.1 spawn类
是Pexpect库的主要对象即接
Pexpect 是一个自动控制的 Python 模块,可以用来ssh、ftp、passwd、telnet 等命令行进行自动交互。 官方网站是 http://www.noah.org/。通过它,可以实现类似
expect 的操作。
例如我们可以用它来写python脚本,实现批量对一系列(大量的、配置相同的)的linux服务器进行操作。
如果你对expect还不太了解,那么可以参考Li
可以使用scp命令实现非交互传输文件,例如将本地文件传输到远程服务器上:
scp local_file remote_username@remote_ip:remote_folder
其中,local_file是本地文件的路径,remote_username是远程服务器的用户名,remote_ip是远程服务器的IP地址,remote_folder是远程服务器上的目标文件夹路径。