1. Paramiko 模块

Paramiko 是 Python 的一个模块,实现了 SSH2 协议,用于与远程服务器的安全通讯,支持 密码 和 证书 的安全连接。

Paramiko 支持 SSH 客户端SFTP 客户端

Paramiko 模块相关网站:

安装 paramiko 模块:

$ python3 -m pip install paramiko

2. SSH 客户端

SSH 连接远程 Linux 主机并执行命令获取结果:

import paramiko
import base64


# 创建 SSH 客户端
ssh_client = paramiko.SSHClient()


# 添加已知的远程 Linux 主机的 host_key(SSH 公钥)
#
# SSH 公钥在 Linux 主机的 "/etc/ssh/" 目录下查找
#
# 公钥的类型一般有一下几种:
#       ssh_host_rsa_key.pub      ->  paramiko.RSAKey
#       ssh_host_ecdsa_key.pub    ->  paramiko.ECDSAKey
#       ssh_host_ed25519_key.pub  ->  paramiko.Ed25519Key
#
rsa_pub_key = paramiko.RSAKey(data=base64.b64decode("AAA..."))
ssh_client.get_host_keys().add("hostname", "ssh-rsa", rsa_pub_key)

# 如果 SSH 端口不是默认的 22, 则添加的 hostname 中需要添加端口, 格式如下:
# ssh_client.get_host_keys().add("[hostname]:port", "ssh-rsa", rsa_pub_key)

# 也可以设置自动添加未知的 host_key(这样简单方便, 但不安全)
# ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

# 也可以从文件中加载 host_keys
# ssh_client.get_host_keys().load("known_hosts.txt")

# 可以加载使用系统本地的 known_hosts, 文件默认位置: "~/.ssh/known_hosts"
# ssh_client.load_system_host_keys()

# 已加载或已添加的 host_keys 可以保存到文件中, 下次可以直接从文件中加载
# ssh_client.get_host_keys().save("known_hosts.txt")

# 连接 Linux 主机时, 远程主机会下发 host_key(SSH 公钥, 用于加密通讯),
# 如果在 system_host_keys() 和 ssh_client.get_host_keys() 中均没有
# 找到与该远程主机相同的 host_key, 说明该主机可能是不安全的, 将抛出异常:
# SSHException: Server 'hostname' not found in known_hosts


# 连接远程 Linux 主机
ssh_client.connect(hostname="hostname",     # 主机名, 端口默认 port=22
                   username="username",     # 用户名
                   password="password")     # 用户密码


# 执行命令, 返回三个参数, 分别对应 标准输入、标准输出、错误输出 三个 IO 通道
stdin, stdout, stderr = ssh_client.exec_command("uname -a")


# 读取 标准输出 和 错误输出 的内容
print(stdout.read().decode("utf-8"))
print(stderr.read().decode("utf-8"))


# 关闭 SSH 客户端
ssh_client.close()

3. SFTP 客户端

SFTP 客户端主要使用 TransportSFTPClient 两个对象。

SFTPClient API: http://docs.paramiko.org/en/stable/api/sftp.html

传输对象 Transport:

# 创建传输对象
t = paramiko.Transport(("hostname", 22))        # <paramiko.Transport>

# 连接服务器
t.connect(username="username", password="password")

# 如果需要安全连接服务器(可以传入 hostkey 校验服务端的 hostkey)
# rsa_pub_key = paramiko.RSAKey(data=base64.b64decode("AAA..."))
# t.connect(hostkey=rsa_pub_key, username="username", password="password")

# 关闭传输对象
# t.close()

SFTP 客户端对象 SFTPClient:

# 根据传输对象, 创建 SFTP 客户端
sftp = paramiko.SFTPClient.from_transport(t)    # <paramiko.sftp_client.SFTPClient>

# 列出目录下的文件或文件夹, 返回 列表
listdir(path)

# 上传文件
sftp.put(localpath, remotepath)

# 下载文件
sftp.get(remotepath, localpath)

# 打开远程文件(所有文件均视为二进制文件)
with sftp.open(filename, mode="r") as f:
    print(f.read())

# 创建文件夹
sftp.mkdir(path)

# 删除文件夹
sftp.rmdir(path)

# 删除文件
sftp.remove(path)

# 重命名
sftp.rename(oldpath, newpath)

# 创建符号链接
sftp.symlink(target_path, path)

# 改变当前路径
sftp.chdir(path)

# 获取当前路径
sftp.getcwd()

# 改变权限
sftp.chmod(path, mode)

# 改变拥有者
sftp.chown(path, uid, gid)

# 获取文件或文件夹的属性信息(权限、拥有者、大小、修改时间等)
attr = sftp.stat(path)
print(attr.st_mode,
      attr.st_gid, 
      attr.st_uid,
      attr.st_size,
      attr.st_atime, 
      attr.st_mtime)

# 获取文件或文件夹的属性信息(不遵循符号链接/别名的相应调用, stat 为遵循)
attr = sftp.lstat(path)

# 列出目录下的所有文件或文件夹的属性信息(权限、拥有者、大小、修改时间等)
for attr in sftp.listdir_attr("."):
    print(attr)

# 关闭 SFTP 客户端
sftp.close()

上传下载文件 代码示例:

import paramiko

# 创建传输对象
t = paramiko.Transport(("hostname", 22))
# 连接服务器
t.connect(username="username", password="password")

# 创建 SFTP 客户端
sftp = paramiko.SFTPClient.from_transport(t)

# 上传文件
sftp.put("localpath", "remotepath")

# 下载文件
sftp.get("remotepath", "localpath")

# 关闭 SFTP 客户端
sftp.close()
# 关闭传输对象
t.close()