使用paramiko通过SFTP下载服务器目录报权限错误如何解决
问题根因
- 触发
PermissionError的直接原因不是本地目录真的没有读写权限,是paramiko.SFTPClient.get()方法的第二个参数必须传入本地目标文件的完整路径,不能直接传目录路径。原代码直接传入已存在的目录路径时,方法内部会尝试以二进制写入模式打开这个目录对象,操作系统会直接拒绝该操作,抛出权限错误。 - 第二个问题是paramiko原生SFTP实现没有提供目录递归下载能力,
get()方法仅支持单文件传输,直接传入远程目录路径本身就不符合方法的参数要求。
排查与解决步骤
- 第一步:基础路径校验
先确认本地目标存储目录C:\Users\Tokyo\PycharmProjects\servers\mydirectory已手动创建,当前运行Python进程的用户对该目录有读写权限。如果是放在C盘系统目录下运行仍偶发权限报错,直接将启动脚本的终端/PyCharm以管理员身份运行即可,或把存储路径改到非系统盘自定义目录规避系统权限管控。 - 第二步:实现递归目录下载逻辑
由于没有内置目录下载能力,需要自行遍历远程目录的所有文件、子目录,在本地按相同层级创建目录后,逐个拉取文件。可直接复用以下实现代码:
import os import paramiko def download_remote_dir(sftp, remote_dir_path, local_dir_path): # 本地对应目录不存在则自动创建 if not os.path.exists(local_dir_path): os.makedirs(local_dir_path) # 遍历远程目录下的所有条目 for file_attr in sftp.listdir_attr(remote_dir_path): remote_full_path = os.path.join(remote_dir_path, file_attr.filename) local_full_path = os.path.join(local_dir_path, file_attr.filename) # 判定条目类型:目录则递归下载,文件则直接拉取 if file_attr.st_mode & 0o40000: download_remote_dir(sftp, remote_full_path, local_full_path) else: sftp.get(remote_full_path, local_full_path) if __name__ == "__main__": # 连接配置 hostname = "替换为实际服务器IP" port = 22 username = "root" password = "替换为实际服务器密码" # 建立SFTP连接 transport = paramiko.Transport((hostname, port)) transport.connect(username=username, password=password) sftp_client = paramiko.SFTPClient.from_transport(transport) # 执行目录下载 remote_target_dir = '/root/.aptos' local_save_dir = r'C:\Users\Tokyo\PycharmProjects\servers\mydirectory' download_remote_dir(sftp_client, remote_target_dir, local_save_dir) # 关闭连接 sftp_client.close() transport.close()
注意事项
- 如果远程目录下存在软链接文件,上述代码默认不会跟随软链接下载目标内容,有对应需求可以在遍历条目时增加软链接判断逻辑单独处理。
- 下载大文件时可以给
sftp.get()传入回调函数,实时显示下载进度,避免长时间无响应。
内容的提问来源于stack exchange,提问作者TokyoDead
相关产品推荐
相关产品推荐

