SSH 远程操作
很多产品的服务端都是运行在 Linux 操作系统上的。
做 自动化测试 或者 运维工作的朋友,经常需要 控制远程 Linux 主机。
干什么事情呢?比如:自动安装环境 、执行自动化测试的一些步骤、数据的自动获取、分析等等。
Paramiko库简介
Python第三方库 Paramiko 就是作为ssh客户端远程控制Linux主机 的。
我们可以执行下面的命令
或者使用国内清华大学的源
要学习自动化操作远程Linux, 首先当然要有一台Linux主机
可以安装VirtualBox虚拟机,在里面安装Linux系统。参考我们的教程
有了Linux主机后,登录进去查看一下IP地址。
本文假设你的Linux主机IP地址是 192.168.2.100
,用户名为 byhy,密码为 byhy5200
接下来,我们就可以使用Paramiko库,执行代码自动化连接,执行命令,就像人工操作一样。
import paramiko
# 创建SSHClient 实例对象
ssh = paramiko.SSHClient()
# 设置信任远程机器,允许访问
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# ssh连接远程机器,参数为 地址、端口、用户名、密码
ssh.connect("192.168.2.100", 22, "byhy", "byhy5200")
# 执行命令,创建目录 logs
ssh.exec_command("mkdir logs")
# 关闭ssh连接
ssh.close()
执行完上面的程序,就会发现远程的Linux主机,多出了一个目录,名为 logs
获取屏幕输出
自动化程序经常 要根据 输出的结果进行判断分析,然后决定下一步怎么做。
比如, 我们要杀死 服务进程, 必须执行ps命令 得到这个进程的ID,才能执行下面kill命令。
怎么获取呢?
可以像这样
cmd = 'ps -ef|grep apiserver |grep -v grep'
# 每次执行命令会返回3个对象,对应标准输入、标准输出、标准错误
stdin, stdout, stderr = ssh.exec_command(cmd)
# 从 标准输出、标准错误 中读取字节
outputBytes = stdout.read()+ stderr.read()
# 解码为字符串
outputStr = outputBytes.decode('utf8')
print(outstr)
ssh.exec_command(cmd) 会返回三个对象 stdin, stdout, stderr,
这三个对象的 类型 是 <class 'paramiko.channel.ChannelFile'>
非常类似我们前面学过的文件对象,分别对应了 远程执行程序 打开的标准输入,标准输出和 标准错误 三个设备文件。
那么如果我们获取了标准输出、和stderr对象,我们只要调用它的read方法就可以获取屏幕上输出的内容了。
命令的前后关联
大家执行一下下面这段代码
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("192.168.2.100", 22, "byhy", "byhy5200")
# 创建目录 testdir
ssh.exec_command("mkdir testdir")
# 进入目录 testdir
ssh.exec_command("cd testdir")
# 查看当前路径
stdin, stdout, stderr = ssh.exec_command("pwd")
print(stdout.read())
ssh.close()
大家会惊奇的发现打印处理目录不是 /home/byhy/testdir
, 而是 /home/byhy/
难道 cd testdir
这命令没有起作用吗?
注意 exec_command 是每次执行都是 新打开一个channel的东西执行,
每个channel都是命令执行的环境,每执行命令都是一个新的执行环境,不在上次执行的环境里面,
相当于 每次都在各自的执行环境里面,和前面的执行环境没有关系。
那么怎么办呢?
可以: 多个命令一起执行,用分号隔开,像这样
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("192.168.2.100", 22, "byhy", "byhy5200")
# 创建目录 testdir
ssh.exec_command("mkdir testdir")
# 用一行命令 进入目录 testdir 并且 查看当前路径
stdin, stdout, stderr = ssh.exec_command("cd testdir;pwd")
print(stdout.read())
ssh.close()
文件传输
有时,我们需要和远程Linux机器之间互相传输文件,包括上传和下载。
比如 自动安装测试环境,经常需要把产品的安装包传送到远程机器上。
paramiko 库提供了 传送文件的方法,如下所示
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("192.168.2.100", 22, "byhy", "byhy5200")
# 打开一个sftp连接,返回sftp连接对象
sftp = ssh.open_sftp()
# put方法上传文件,第1个参数是本地路径,第2个参数是远程路径
sftp.put('install.zip', '/home/byhy/install.zip')
# get方法下载文件,第1个参数是远程路径,第2个参数是本地路径
sftp.get('/home/byhy/log.zip', 'd:/log.zip')
# 关闭sftp连接
sftp.close()
# 关闭ssh连接
ssh.close()
注意,
使用put方法上传文件时,第2个参数是远程路径,当前登录的用户必须有该路径的写权限
使用get方法上传文件时,第1个参数是远程路径,当前登录的用户必须有该路径的读权限