paramiko是SSHv2协议的Python实现,提供了客户端与服务器功能。虽然它利用Python C扩展进行低级加密,但paramiko本身是一个围绕SSH网络概念的纯Python接口。
paramiko最开始是用Python对ssh进行的一个封装,封装就是对一些面向对象的方法,就是把变量和方法给他包装起来。提供一些外部的api,给大家很方便的使用它。比如ssh,它很复杂但通过它的一个包装把它很简单的提供给大家使用。
安装
pip install paramiko
连接远程服务器
安装完paramiko,现在我们来尝试连接一下我们的远程服务器。要连接远程服务器,需要以下几个重要步骤:首先要确保这台远程服务器处于开机状态,并且已经开启了默认端口为22的ssh
服务,而且还要知道它的用户名与密码。下面就来举一个简单的栗子来连接我们的远程服务器,并且查看一下远程服务器的日期:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接远程服务器
client.connect(hostname="192.168.0.158", port=22, username="root", password="1")
stdin, stdout, stderr = client.exec_command("date")
print stdout.readline()
client.close()
确保服务器与ssh
服务开启正常的情况下,执行完如下代码,将会输出如下内容:
Mon Apr 23 10:38:35 CST 2018
下面,我们简单分析一下上面的代码。可以看到,首先在当前脚本文件中需要先导入paramiko
库,然后创建一个SSHClient
实例对象,SSHClient
是paramiko
库提供给我们的一个api类,因为paramiko
库它是一个基于ssh
协议的一个封装,而SSHClient
就是它提供的一个访问远程和文件传输的一个最基本的接口。set_missing_host_key_policy
就是设置它的host key,就是一个设置公钥和处理公钥的一个机制,一般采用paramiko
的自动添加的机制。而后就是一个连接的操作connect
,它提供了几个重要的参数:主机地址,端口,用户名和密码,我们可以将服务器中的这些信息传递至这些参数,就可以完成一个连接的操作。此外,connect
方法还提供了一个timeout
,用于设置连接超时的时间,超过这个时间将会发生异常。exec_command
就是一个输入linux命令的封装了,我们只需要将linux的命令操作以字符串形式传递进去即可,它将返回三个数据,输入、输出和错误,一般情况下,我们只需要关注输出信息即可。
对脚本进行封装
在日常的开发中,我们写代码不仅仅只是把功能实现了就可以了,常常还需要考虑到代码的可重用行,代码的可移植性。要实现这两个需求,就要防止代码中出现硬编码情况,什么是硬编码,也就是说,在你的代码中有一些变量是死的,不能进行活用,其他人可能根本就不能使用你那变量里的值,需要对其进行修改,才可使用,这就是硬编码。观察上面的脚本可以看出,对于一些服务器的信息,以及linux的命令,就是硬编码。为了消除硬编码情况,我们可以将这些值,以参数的形式进行传递,修改后如下:
import paramiko
def ssh_cmd(host, port, username, password, cmd):
"""
连接远程服务器并执行命令
:param host:主机地址
:param port:端口
:param username:用户名
:param password:密码
:param cmd:命令
"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接远程服务器
client.connect(hostname=host, port=port, username=username, password=password)
stdin, stdout, stderr = client.exec_command(cmd)
print stdout.readline()
client.close()
因为paramiko
是基于ssh
协议的一个封装,所以当它使用完毕之后,记得将它close。除了将服务器信息以参数的形式传递进来,用于消除硬编码的问题,我们还可以将这些服务器的信息写入配置文件,用读取文配置文件的方式,将其读出来。我们可以引入一个ConfigParser
库,它可以把配置文件很好的读出来。首先我们先创建一个配置文件ubuntu.ini
,配置具体如下:
[ssh]
host = 192.168.0.188
port = 22
username = root
password = 1
timeout = 5
将配置文件信息配置完毕之后,我们将上面的脚本进行修改,代码如下:
import paramiko,ConfigParser
def ssh_cmd(ini_file, cmd):
"""
连接远程服务器并执行命令
:param ini_file:配置文件路径
:param cmd:命令
"""
config = ConfigParser.ConfigParser()
config.read(ini_file)
host = config.get("ssh","host")
port = int(config.get("ssh","port"))
username = config.get("ssh","username")
password = config.get("ssh","password")
timeout = int(config.get("ssh","timeout"))
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接远程服务器
client.connect(hostname=host, port=port, username=username, password=password, timeout=timeout)
stdin, stdout, stderr = client.exec_command(cmd)
print stdout.readline()
client.close()
因为经过ConfigParser
库,从配置文件中读取的内容都是str
,但是timeout
与port
参数都必须为int
,所以在参数传递之前,需进行类型转换。代码经过这样的封装,就将原本的代码,从一个硬编码到一个更优雅的一个实现的过程