香港建站网站/国产系统2345
文章目录
- 知识准备
- 什么是Pexpect ?
- pexpect的核心类和函数
- pexpect模块的缺陷
- pexpect项目实战代码
- 项目执行效果
知识准备
- 实现ssh无密码连接。
- 一台或者两台服务器。
什么是Pexpect ?
**Pexpect 用来实现与 ssh、ftp 、telnet 等程序的自动交互。**是 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块。
pexpect的核心类和函数
-
直接进程运行run()函数, 返回结果和状态。
import pexpectcmd_result, exitstatus = pexpect.run('hostname', withexitstatus=True) print("命令执行结果: ", cmd_result.decode('utf-8')) print("命令执行的状态码: ", exitstatus)
执行结果如下:
命令执行结果: foundation0.ilt.example.com 命令执行的状态码: 0
-
启动子进程运行spawn()函数, 读取缓冲区数据
- 如果正则匹配成功
- 发送指令(send、sendline、sendcontrol)
- 退出当前会话, 进入终端交互式命令行
- 如果正则匹配不成功, 等待超时(TIMEOUT)或者子进程退出(pexpect.EOF)。
- 正则不管是否匹配成功, 都可以打印输出匹配的缓冲区结果(before和after)
- 如果正则匹配成功
pexpect模块的缺陷
- 依赖终端命令的方式
- 不同的ssh登陆环境兼容性差
pexpect项目实战代码
下面的代码通过子进程运行spawn函数的方式实现了SSH客户端登陆的两种方式:
- login_ssh_passwd函数是密码登录的封装。
- login_ssh_key函数是密钥登陆的封装。
import pexpect
# logging:专门做日志记录或者处理的模块。
import logging# 日志的基本配置
# 官方符网站基本配置及使用: https://docs.python.org/zh-cn/3/howto/logging.html#logging-basic-tutorial
logging.basicConfig(level=logging.DEBUG, # 控制台打印的日志级别filename='message.log', # 日志文件位置filemode='a', # 写入文件的模式,a是追加模式,默认是追加模式# 日志格式format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
)class SSH(object):def login_ssh_passwd(self, hostname, username, password, port=22):"""用于pexpect实现ssh自动化用户密码登录"""print("ssh -p%s %s@%s" % (port, username, hostname))if port and username and password:ssh = pexpect.spawn("ssh -p%s %s@%s" % (port, username, hostname))status_code = ssh.expect(['password', 'continue connecting (yes/no)?'], timeout=5)if status_code == 0:ssh.sendline(password)elif status_code == 1:ssh.sendline('yes\n')ssh.expect('password: ')ssh.sendline(password)index = ssh.expect(["#", pexpect.EOF, pexpect.TIMEOUT])if index == 0:print("logging in as root!")logging.info("logging in as root!")ssh.interact()elif index == 1:print("logging process exit!")logging.error("logging process exit!")elif index == 2:print("logging timeout exit!")logging.error("logging timeout exit!")else:print("Parameter error!")logging.error("Paramiko error!")def login_ssh_key(self, hostname, keyfile, username, port=22):"""用于实现pexpect实现ssh的自动化密钥管理"""print("ssh -i %s -p%s %s@%s" % (keyfile, port, username, hostname))if hostname and keyfile and username and port:ssh = pexpect.spawn("ssh -i %s -p%s %s@%s" % (keyfile, port, username, hostname))status_code = ssh.expect([pexpect.TIMEOUT, 'continue connecting (yes/no)?'], timeout=5)if status_code == 1:ssh.sendline('yes\n')index = ssh.expect(["#", pexpect.EOF, pexpect.TIMEOUT])if index == 0:print("logging in as root!")logging.info("logging in as root!")# 进入交互式环境ssh.interact()elif index == 1:print("logging process exit!")logging.error("logging process exit!")elif index == 2:print("logging timeout exit!")logging.error("logging timeout exit!")else:print("Paramiko error!")logging.error("Parameter error!")def main():sshClient = SSH()# sshClient.login_ssh_passwd('172.25.254.197', 'root', 'redhat')# 必须做过无密码连接sshClient.login_ssh_key('172.25.254.197','/root/.ssh/id_rsa', 'root', )if __name__ == '__main__':main()