python3.8实现自动化交互程序

一、基本介绍

安装

pip3 install pexpect

在Pexpect中有两种重要的方法– expect()send()(或 sendline() 类似于send() 方法+ \n,就是可以换行)。

expect() 方法等待子应用程序返回给定的字符串。
您指定的字符串是一个正则表达式,因此您可以匹配复杂的模式。
send() 方法将字符串写入子应用程序。从子应用程序的角度来看,就像有人在终端上键入文本一样。

每次调用 expect() 后, 子应用程序的 beforeafter 属性将被设置为可以被打印的文本。该 before 属性将包含子应用程序返回的所有文本,直到匹配上期望的字符串模式为止。该 after 字符串将包含与预期模式匹配的文本。match 属性设置为 re match对象。

执行一个创建密钥对的命令

[test@VM-0-11-centos ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):

使用模块 pexpect 尝试捕获到响应的字符串

In [1]: import pexpect

In [2]: child = pexpect.spawn("ssh-keygen")

In [3]: child.expect("/root/.ssh/id")
Out[3]: 0

In [4]: child.before
Out[4]: b'Generating public/private rsa key pair.\r\nEnter file in which to save the key ('

In [5]: child.after
Out[5]: b'/root/.ssh/id'

实例演示

先删除或者移动已经有的 密钥对

下面的指令是先测试是否存在 .ssh 目路,如果存在则改名,防止已经建立的信任关系失效。

test -d  ~/.ssh && mv ~/.ssh   ~/myssh

In [1]: import pexpect

In [2]: cmd = "ssh-keygen"

In [3]: child = pexpect.spawn(cmd)  // 执行 shell 命令,生成子程序

// 捕获子程序输出的字符串, 因为 ) 会被 python 识别解释,所以这里使用了 [)]
In [4]: child.expect(".ssh/id_rsa[)]")
Out[4]: 0

// 根据子程序的需要,发送进一步的指令
// 这里是直接输入一个回车键,相当于按下了回车键
In [5]: child.sendline()
Out[5]: 1

// 继续捕获
In [6]: child.expect("no passphrase.:")
Out[6]: 0

// 这里是打印出了匹配模式之前的输出内容,不是必须的操作
// 只是进行简单的验证子程序输出的内容而已
In [7]: child.before
Out[7]: b": \r\nCreated directory '/home/test/.ssh'.\r\nEnter passphrase (empty for "

// 这里是输出的字符串中,匹配到的那部分字符串
In [8]: child.after
Out[9]: b'no passphrase):'

In [9]: child.sendline()
Out[9]: 1

In [10]: child.expect("again:")
Out[10]: 0

In [11]: print(child.before.decode()+child.after.decode())

Enter same passphrase again:

In [12]: child.sendline()
Out[12]: 1

In [13]: child.close()

In [14]: !ls .ssh
id_rsa	id_rsa.pub

In [15]:

额外的小方法

对于创建 ssh 的密钥对,其实可以使用如下的 shell 命令非交互式的创建自己的密钥对, 上面的例子只是为了演示 pexpect 而已。

ssh-keygen -t rsa -f ~/.ssh/id_rsa  -N ""
  • -t 指定密钥加密类型
  • -f 指定私钥文件的输出路径
  • -N 新的密钥的加密密码,"" 标识空(或者说是不对私钥进行加密)

二、应对一条命令多种输出内容的情况

在某些情况下,我们执行的命令,有可能会出现多种情况的返回结果。
比如,在要求输入密码的时候,可能会输入正确的密码,返回的是正常的进一步的命令提示符,也有可能输入了错误的密码,此时返回的是要求再次输入密码的提示内容。

比如刚才上面创建密钥对的命令,假如密钥对已经存在,中间会多提示一条是否要进行覆盖现有的密钥对,并且期望输入的是 y 或者 n

测试情况如下

[test@VM-0-11-centos ~]$ ls .ssh/
id_rsa  id_rsa.pub
[test@VM-0-11-centos ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_rsa):
/home/test/.ssh/id_rsa already exists.
Overwrite (y/n)? n
[test@VM-0-11-centos ~]$

当输入 n 并回车之后, 表明你不覆盖现有的密钥对,程序也就不会继续创建新的密钥对了。

假如输入 y 并回车,程序会继续创建新的密钥对,并覆盖原来的。

[test@VM-0-11-centos ~]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/test/.ssh/id_rsa):
/home/test/.ssh/id_rsa already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/test/.ssh/id_rsa.
Your public key has been saved in /home/test/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:OMu/CTZd4kwnC+uD1/2S8Nqry6iUG/112Z1Vu452EhI test@VM-0-11-centos
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|                .|
|       .   E    o|
|      + S o .  ..|
|     + X.* . + .+|
|    +.O.=+..+ oo.|
|   ..=oB.+=. oo. |
|    ooo.X=o+o.o. |
+----[SHA256]-----+
[test@VM-0-11-centos ~]$

应对上面的情况,pexpect 模块的 expect 方法可以接受一个列表类型的参数。这个列表中包含了多个正则表达式,每个正则表达式代表了可能会出现的字符串结果。比如:

i = child.expect["Overwrite", "no passphrase"]

i 的值是捕获列表的索引号, 用于判断实际捕获到了列表中的哪个字符串,比如:

匹配到 "Overwrite"i 的值就是 0,
匹配到 "no passphrase"i 的值就是 1, 依次类推。

所以代码优化后应该像下面的样子:

In [15]: import pexpect
In [16]: cmd = "ssh-keygen"

In [17]: child = pexpect.spawn(cmd)

In [18]: child.expect(".ssh/id_rsa[)]:")
Out[18]: 0

In [20]: child.sendline()
Out[7]: 1

In [8]: i = child.expect(["Overwrite", "no passphrase"])

In [10]: if i == 0:
    ...:     child.sendline("y")
    ...:     child.expect("empty for no passphrase")
    ...:     child.sendline()
    ...: elif i == 1:
    ...:     child.expect("empty for no passphrase")
    ...:     child.sendline()
    ...:

In [11]: child.expect("again:")
Out[11]: 0

In [12]: child.sendline()
Out[12]: 1

In [13]: child.close()

In [14]: !ls ~/.ssh
id_rsa	id_rsa.pub


三、小练习

练习写一个 MySQL初始化后,修改默认密码的脚本
脚本要实现的功能:

  1. 过滤出默认密码
  2. 修改默认密码
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shark_西瓜甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值