目录
一、paramiko介绍
有了paramiko以后,我们可以在python代码中直接使用SSH协议对远程服务器执行操作,而不是通过ssh命令对远程服务器进行操作。
paramiko有两个核心组件,SSHClient和SFTPClient。SSHClient的作用类似与SSH,是对SSH会话的封装,该类封装了传输(Transport)、
通道(Channel)及SFTPClient建立的方法(open_sftp),一般用于远程命令对的执行。SFTPClient的作用类似与linux的sftp命令,
是对SFTP的封装,用于实现远程文件操作,如文件上传、下载、修改文件权限等操作。
paramiko中的几个基本名词:
Channel:是一种类Socket,一种安全的SSH传输通道;
Transport:是一种加密的会话,使用时会同步创建了一个加密的Tunnels(隧道),这个Tunnels叫做Channel;
Session:是client与server保持连接的对象,用connect()/start_client()/start_server()开始会话。
二、paramiko基本使用
connect() 方法
实现远程服务器的连接与认证,对于该方法只有hostname是必传参数。
常用参数:hostname、port、username、password、pkey、key_filename、timeout、allow_agent、look_for_keys、compress
pkey:私钥方式用于身份认证;
key_filename:一个文件名或文件列表,指定私钥文件;
timeout:可选的tcp连接超时时间;
allow_agent:是否允许连接到SSH代理,默认为True允许;
look_for_keys:是否在~/.ssh中搜索私钥文件,默认为True允许;
compress:是否打开压缩;
set_missing_host_key_policy()方法
设置远程服务器没有在know_hosts文件中记录时的应对策略
AutoAddPolicy 自动添加主机名或主机密钥到本地HostKeys对象,不依赖load_system_host_key的配置。即新建立ssh连接时不需要再输入yes或no进行确认;
WarningPolicy 用于记录一个未知的主机密钥的python警告。并接受,功能上和AutoAddPolicy类似。但是会提示是新连接;
RejectPolicy 自动拒绝未知的主机名和密钥,依赖load_system_host_key的配置。此为默认选项;
exec_command()方法:在远程服务器上执行Linux命令
open_sftp(): 在当前的SSH会话的基础上创建一个ftp会话,该方法会返回一个SFTPClient对象
三、代码实践
# -* coding:utf-8
import paramiko
import os
def ssh_connect_device(ip, port, username, password, timeout=65534):
"""
封装连接SSH方法
:param ip:
:param port:
:param username:
:param password:
:param timeout: 超时时间
:return:
"""
try:
ssh = paramiko.SSHClient()
# 设置远程服务器没有在know_hosts文件中记录时的应对策略
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, port, username, password, timeout=timeout)
return ssh
except Exception as e:
print("ssh_connect_device error: %s" % (e))
return None
def ssh_reconnect_device(ip, port, username, password, times=3, timeout=65534):
"""
times次尝试连接服务器
:param ip:
:param port:
:param username:
:param password:
:param times:
:param timeout:
:return:
"""
ssh = None
for i in range(times):
ssh = ssh_connect_device(ip, port, username, password, timeout)
if ssh is not None:
print("SSH成功")
return ssh
return ssh
def ssh_cmd(ssh, cmd, timeout=65534):
"""
执行Linux命令
:param ssh:
:param cmd:
:param timeout:
:return:
"""
# stdout为正确输出,stderr为错误输出,同时只能有一个变量有值
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=timeout)
stdout = stdout.read().decode()
stderr = stderr.read().decode()
result = stdout if stdout else stderr
return result
# 操作文件的sftp对象
def create_sftp(ip, port, username, password):
try:
# 实例化transport对象
transport = paramiko.Transport((ip, port))
# 连接SSH服务
transport.connect(username=username, password=password)
# 获取SFTP实例
sftp = paramiko.SFTPClient.from_transport(transport)
return sftp
except Exception as e:
print("create_sftp failed, please check host: %s" % (ip))
print(e)
return None
# 下载文件
def sftp_get_file(sftp, localpath, remotepath):
try:
sftp.get(remotepath, localpath)
print("文件下载成功!地址为:%s" % localpath)
return True
except Exception as e:
print("sftp_get_file failed, error: %s" % (e))
return False
# 上传文件到服务器
def sftp_put_file(sftp, localpath, remotepath):
try:
sftp.put(localpath, remotepath)
print("文件上传成功!地址为:%s" % remotepath)
return True
except Exception as e:
print("sftp_put_file failed, error: %s)" % (e))
return False
# 连接SSH,执行命令
def ssh_exe_cmd(cmd, ip, username, password, port=22, times=3, timeout=65534):
ssh = ssh_reconnect_device(ip, port, username, password, times, timeout)
if ssh is None:
print("ssh_reconnect_device failed, please check host: %s" % (ip))
return ssh
result = ssh_cmd(ssh, cmd, timeout)
ssh.close()
return result
# 创建连接并获取linux文件
def create_sftp_get_file(ip, port, username, password, localpath, remotepath):
"""
:param ip:
:param port:
:param username:
:param password:
:param localpath: 本地地址
:param remotepath: 服务器地址
:return: result
"""
sftp = create_sftp(ip, port, username, password)
if sftp is None:
print("create_sftp_get_file create sftp failed, please check host: %s" % (ip))
return sftp
ret = sftp_get_file(sftp, localpath, remotepath)
sftp.close()
return ret
# 创建连接并将文件上传到服务器
def create_sftp_put_file(ip, port, username, password, localpath, remotepath):
sftp = create_sftp(ip, port, username, password)
if sftp is None:
print("create_sftp_put_file create sftp failed, please check host: %s" % (ip))
return sftp
ret = sftp_put_file(sftp, localpath, remotepath)
sftp.close()
return ret
if __name__ == '__main__':
# 执行命令测试
print(ssh_exe_cmd("df", "*.*.*.*", "root", "******"))
# 获取服务器文件测试
x = create_sftp_get_file("*.*.*.*", 22, 'root', '*******', "D:/Python/code/demo/Common/xx",
"/home/111")
# 文件上传到服务器测试
create_sftp_put_file("*.*.*.*", 22, 'root', '*******', "D:/Python/code/demo/Common/xx",
"/home/xxx")