14.Python网络编程—Pexpect & paramiko

14.1 Pexpect简介

  • Pexpect 是 Don Libes 的 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其 自动交互的 Python 模块。
  • Pexpect 的使用范围很广,可以用来实现与 ssh、ftp 、telnet 等程序的自动交互;可以用来自动复制软件安装包并在不同机器自动安装;还可以 用来实现软件测试中与命令行交互的自动化。

14.2 Pexpect 提供的 run() 函数

14.2.1 run() 的定义

  • 函数 run 可以用来运行命令,其作用与 Python os 模块中 system() 函数相似。 run() 是通过 Pexpect类实现的。
  • 如果命令的路径没有完全给出,则 run 会使用 which 命令尝试搜索命令的路径 。

14.2.2 使用 run()执行 svn 命令

  • 与 os.system() 不同的是,使用 run() 可以方便地同时获得命令的输出结果与命令的退出状态 。

14.2.3 run() 的返回值

  • command_out 中保存的就是 /bin 目录下的内容。

14.3 Pexpect 提供的 spawn() 类

14.3.1 使用 Pexpect 启动子程序

  • spawn 的构造函数
  • spawn是Pexpect模块主要的类,用以实现启动子程序,它有丰富的方法与子程序交互从而实现用户对子程序的控制。
  • 它主要使用pty.fork() 生成子进程,并调用 exec() 系列函数执行 command 参数的内容。
  • 当子程序需要参数时,还可以使用一个参数的列表
  • 在构造函数中,maxread 属性指定了 Pexpect 对象试图从 tty 一次读取的最大字节数,它的默认值是2000字节 。
  • 由于需要实现不断匹配子程序输出, searchwindowsize 指定了从输入缓冲区中进行模式匹配的位置,默认从开始匹配。
  • logfile 参数指定了 Pexpect 产生的日志的记录位置。
  • 还可以将日志指向标准输出
  • 如果不需要记录向子程序输入的日志,只记录子程序的输出,可以使用

14.3.2 使用 Pexpect 控制子程序

为了控制子程序,等待子程序产生特定输出,做出特定的响应,可以使用expect 方法。

  • expect() 定义
    • 在参数中: pattern 可以是正则表达式, pexpect.EOF pexpect.TIMEOUT ,或者由这些元素组成的列表。
    • 需要注意的是,当pattern 的类型是一个列表时,且子程序输出结果中不止一个被匹配成功,则匹配返回的结果是缓冲区中最先出现的那个元素,或者是列表中最左边的元素。
    • 使用 timeout 可以指定等待结果的超时时间 ,该时间以秒为单位。
    • 当超过预订时间时, expect 匹配到pexpect.TIMEOUT。
    • 如果难以估算程序运行的时间,可以使用循环使其多次等待直至等待运行结束
    • expect() 在执行中可能会抛出两种类型的异常分别是 EOF and TIMEOUF,其中 EOF 通常代表子程序的退出, TIMEOUT 代表在等待目标正则表达式中出现了超时。
    • 如果难以估算程序运行的时间,可以使用循环使其多次等待直至等待运行结束。
    • expect() 在执行中可能会抛出两种类型的异常分别是 EOF and TIMEOUF,其中 EOF 通常代表子程序的退出, TIMEOUT 代表在等待目标正则表达式中出现了超时。
    • expect 不断从读入缓冲区中匹配目标正则表达式,当匹配结束时 pexpect 的before 成员中保存了缓冲区中匹配成功处之前的内容, pexpect 的 after 成员保存的是缓冲区中与目标正则表达式相匹配的内容。
    • child.before 保存的就是在根目录下执行 ls 命令的结果。
  • send 系列函数
    • 这些方法用来向子程序发送命令,模拟输入命令的行为。
    • 与 send() 不同的是sendline() 会额外输入一个回车符 ,更加适合用来模拟对子程序进行输入命令的操作。
    • 当需要模拟发送 “Ctrl+c” 的行为时,还可以使用 sendcontrol() 发送控制字符。
  • 发送 ctrl+c
    • 由于 send() 系列函数向子程序发送的命令会在终端显示,所以也会在子程序的输入缓冲区中出现,因此不建议使用 expect 匹配最近一次 sendline() 中包含的字符。
    • 否则可能会在造成不希望的匹配结果。
  • interact() 定义
    • Pexpect还可以调用interact() 让出控制权,用户可以继续当前的会话控制子程序。
    • 用户可以敲入特定的退出字符跳出,其默认值为“^]” 。

14.4 Paramiko

  • paramiko是基于Python实现的SSH2远程安全连接,支持认证及密钥方式。可以实现远程命令执行、文件传输、中间SSH代理等功能,相对于Pexpect,封装的层次更高,更贴近SSH协议的功能
  • paramiko包含两个核心组件
    • 一个为SSHClient类
    • 另一个为SFTPClient类。

14.4.1 SSHClient类

  • SSHClient类是SSH服务会话的高级表示,该类封装了传输(transport)、通道(channel)及SFTPClient的校验、建立的方法,通常用于执行远程命令。
  • connect方法
    • connect方法实现了远程SSH连接并校验
  • 参数说明:
    • hostname(str类型),连接的目标主机地址;
    • port(int类型),连接目标主机的端口,默认为22;
    • username(str类型),校验的用户名(默认为当前的本地用户名);
    • password(str类型),密码用于身份校验或解锁私钥;
    • pkey(Pkey类型),私钥方式用于身份验证;
    • key_filename(str or list(str)类型),一个文件名或文件名列表,用于私钥的身份验证;
    • timeout(float类型),一个可选的超时时间(以秒为单位)的TCP连接;
    • allow_agent(bool类型),设置为False时用于禁用连接到SSH代理;
    • look_for_keys(bool类型),设置为False时用于来禁用在~/.ssh中搜索私钥文件;
    • compress(bool类型),设置为True时打开压缩。
  • exec_command方法
    • 远程命令执行方法,该命令的输入与输出流为标准输入(stdin)、输出(stdout)、错误(stderr)的Python文件对像。
  • 参数说明:
    • command(str类型),执行的命令串;
    • bufsize(int类型),文件缓冲区大小,默认为-1(不限制)
  • load_system_host_keys方法
    • 加载本地公钥校验文件,默认为~/.ssh/known_host,非默认路径需要手工指定。
    • ~/.ssh/known_hosts的作用:当ssh会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。
    • 当下次访问相同计算机时,OpenSSH会核对公钥。
    • 如果公钥不同,OpenSSH会发出警告
  • 参数说明:
    • filename(str类型),指定远程主机公钥记录文件。
  • set_missing_host_policy方法
    • 设置连接的远程主机没有主机密钥或HostKeys对象时的策略,目前支持三种,分别是AutoAddPolicy、RejectPolicy(默认)、WarningPolicy,仅限用于SSHClient类。
    • AutoAddPolicy,目标添加主机名及主机密钥到本地HostKeys对象,并将其保存,不依赖load_system_host_keys()的配置,即~/.ssh/hnown_hosts不存在也不产生影响;
    • RejectPolicy,自动拒绝未知的主机名和密钥,依赖load_system_host_keys()的配置;
    • WarningPolicy,用于记录一个未知的主机密钥的Python警告,并接收它,功能上AutoAddPolicy相似,但未知主机会有告警。

14.4.2 SFTPClient类

  • SFTPClient作为一个SFTP客户端对象,根据SSH传输协议的sftp会话,实现远程文件操作,比如文件上传、下载、权限、状态等操作。
  • from_transport方法
    • 创建一个已连通的SFTP客户端通道。
  • 参数说明
    • t(transport),一个已通过验证的传输对象。
  • put方法
    • 上传本地文件到远程SFTP服务端
  • 参数说明:
    • localpath(str类型),需上传的本地文件(源);
    • remotepath(str类型),远程路径(目标);
    • callback(funcation(int,int)),获取已接收的字节数及总传输字节数,以便回调函数调用,默认为None;
    • confirm(bool类型),文件上传完毕后是否调用stat()方法,以便确认文件的大小。
  • get方法
    • 从远程SFTP服务端下载文件到本地。
  • 参数说明:
    • remotepath(str类型),需要下载的远程文件(源);
    • callback(funcation(int,int)),获取已接收的字节数及总和传输字节数,以便回调函数调用,默认为None.
  • 其它方法
  • SFTPClient类其它常用方法说明:
    • mkdir,在SFTP服务端创建目录,如sftp.mkdir("/home/userdir",mode=0777),默认模式是0777(八进制),在某些系统上,mode被忽略。在使用它的地方,当前的umask值首先被屏蔽掉。
    • remove,删除SFTP服务端指定目录,如sftp.remove("/home/userdir")。
    • rename,重命名SFTP服务端文件或目录,如sftp.rename("/home/test.sh","/home/testfile.sh")
    • stat,获取远程SFTP服务端指定文件信息,如sftp.stat("/home/testfile.sh")。
    • listdir,获取远程SFTP服务端指定目录列表,以Python的列表(List)形式返回,如sftp.listdir("/home")。

14.4.3 实验

In:

pip install paramiko

out:

Requirement already satisfied: paramiko in d:\programdata\anaconda3\lib\site-packages (2.7.1)
Requirement already satisfied: cryptography>=2.5 in d:\programdata\anaconda3\lib\site-packages (from paramiko) (2.7)
Requirement already satisfied: pynacl>=1.0.1 in d:\programdata\anaconda3\lib\site-packages (from paramiko) (1.4.0)
Requirement already satisfied: bcrypt>=3.1.3 in d:\programdata\anaconda3\lib\site-packages (from paramiko) (3.1.7)
Requirement already satisfied: cffi!=1.11.3,>=1.8 in d:\programdata\anaconda3\lib\site-packages (from cryptography>=2.5->paramiko) (1.12.3)
Requirement already satisfied: asn1crypto>=0.21.0 in d:\programdata\anaconda3\lib\site-packages (from cryptography>=2.5->paramiko) (1.0.1)
Requirement already satisfied: six>=1.4.1 in d:\programdata\anaconda3\lib\site-packages (from cryptography>=2.5->paramiko) (1.12.0)
Requirement already satisfied: pycparser in d:\programdata\anaconda3\lib\site-packages (from cffi!=1.11.3,>=1.8->cryptography>=2.5->paramiko) (2.19)
Note: you may need to restart the kernel to use updated packages.

In:

import paramiko

主机:xxx.xxx.xxx.xxx
用户:student
密码:xxxxxx
端口:xx
In:

sshc = paramiko.SSHClient()

In:

sshc.set_missing_host_key_policy(paramiko.AutoAddPolicy())

In:

sshc.connect(hostname='192.168.199.175',port=22,username='student',
            password='123456')

In:

stdin,stdout,stderr  = sshc.exec_command('df -m')

In:

print(stdout.read().decode('utf-8'))

out:

Filesystem     1M-blocks  Used Available Use% Mounted on
/dev/sda1          32354  6759     23946  23% /
tmpfs               1917     1      1917   1% /dev/shm

你可能感兴趣的:(python网络编程,python)