跳转至

SSH 远程操作

很多产品的服务端都是运行在 Linux 操作系统上的。

做 自动化测试 或者 运维工作的朋友,经常需要 控制远程 Linux 主机。

干什么事情呢?比如:自动安装环境 、执行自动化测试的一些步骤、数据的自动获取、分析等等。

Paramiko库简介

Python第三方库 Paramiko 就是作为ssh客户端远程控制Linux主机 的。

我们可以执行下面的命令

pip install paramiko 

或者使用国内清华大学的源

pip install paramiko –i https://pypi.tuna.tsinghua.edu.cn/simple 


要学习自动化操作远程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个参数是远程路径,当前登录的用户必须有该路径的读权限