使用Paramiko向SFTP服务器传输大文件时遇OSError: Failure错误
问题描述
运行在Windows Server 2016 Standard虚拟机上的Python脚本,通过任务计划程序执行,需将共享驱动器上的4个文件(大小分别为25MB、55MB、900MB、2GB)上传至SFTP服务器。前三个小文件上传成功,但2GB的大文件上传时触发OSError: Failure,且报错后数小时内无法上传任何文件——即使小文件也会立即报错,需等待数小时或次日才能恢复。
上传代码
hostname = 'ftp_server_name' username = 'username' password = 'password' keypath = 'Sftp_Key' known_hosts = 'known_hosts.txt' import paramiko mykey = paramiko.RSAKey.from_private_key_file(keypath, password) ssh_client = paramiko.SSHClient() ssh_client.load_host_keys(known_hosts) ssh_client.connect( hostname=hostname, username=username, allow_agent=True, pkey=mykey, disabled_algorithms={'pubkeys': ['rsa-sha2-256', 'rsa-sha2-512']} ) tr = ssh_client.get_transport() tr.default_max_packet_size = 10000000000 tr.default_window_size = 10000000000 sftp_client = ssh_client.open_sftp() sftp_client.put( r'\\path\to\origin\on\shared\drive\file_1.csv', '/root/folder/path/to/destination/file_1.csv' ) sftp_client.put( r'\\path\to\origin\on\shared\drive\file_2.csv', '/root/folder/path/to/destination/file_2.csv' ) sftp_client.put( r'\\path\to\origin\on\shared\drive\file_3.csv', '/root/folder/path/to/destination/file_3.csv' ) sftp_client.put( r'\\path\to\origin\on\shared\drive\file_4.csv', '/root/folder/path/to/destination/file_4.csv' ) print(sftp_client.listdir()) sftp_client.close() ssh_client.close()
错误堆栈
Traceback (most recent call last): File "H:\folder\scripts\test_sftp_copy.py", line 45, in <module> ftp_client.put( File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\sftp_client.py", line 759, in put return self.putfo(fl, remotepath, file_size, callback, confirm) File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\sftp_client.py", line 716, in putfo size = self._transfer_with_callback( File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\sftp_client.py", line 679, in _transfer_with_callback writer.write(data) File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\file.py", line 405, in write self._write_all(data) File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\file.py", line 522, in _write_all count = self._write(data) File "C:\Users\MeUser\Anaconda3\lib\site-packages\paramiko\sftp_file.py", line 208, in _write t, msg = self.sftp._read_response(req) File "C:\Users\A-AChiap\Anaconda3\lib\site-packages\paramiko\sftp_client.py", line 874, in _read_response self._convert_status(msg) File "C:\Users\A-AChiap\Anaconda3\lib\site-packages\paramiko\sftp_client.py", line 907, in _convert_status raise IOError(text) OSError: Failure.
技术分析
大文件上传失败原因
- 服务器端限制:多数SFTP服务器(如OpenSSH)默认对单个文件大小、会话传输量或用户磁盘配额有上限,2GB文件可能触发这类限制,或目标磁盘空间不足。
- 参数配置过载:你设置的
default_max_packet_size和default_window_size(10GB)远超SFTP协议常规范围(通常最大1GB),可能导致服务器缓冲区溢出,直接中断会话。 - 网络与会话异常:大文件传输时长久,网络波动可能导致会话半开,服务器未正确处理中断后的资源回收。
报错后无法上传的原因
- 服务器资源锁定:大文件上传失败时,服务器可能未释放残留的会话资源(如文件句柄、内存缓冲区),导致该用户的后续请求被拒绝,直到服务器自动回收资源或会话超时。
- 临时封禁机制:部分SFTP服务器会对异常中断的会话IP/用户进行临时封禁,防止恶意请求,封禁时长通常为几小时。
解决建议
1. 调整传输参数
将数据包大小和窗口大小调整为合理范围,建议设置为64MB(67108864),平衡传输效率与服务器负载:
tr.default_max_packet_size = 67108864 tr.default_window_size = 67108864
2. 分块传输大文件
使用putfo配合分块读取,避免一次性加载大文件到内存,降低单次传输压力:
def upload_large_file(sftp, local_path, remote_path, chunk_size=67108864): with open(local_path, 'rb') as f: sftp.putfo(f, remote_path, callback=lambda transferred, total: print(f"Transferred {transferred}/{total} bytes")) # 替换原有的file_4.csv上传代码 upload_large_file(sftp_client, r'\\path\to\origin\on\shared\drive\file_4.csv', '/root/folder/path/to/destination/file_4.csv')
3. 强制会话清理
添加异常捕获与强制关闭逻辑,确保上传失败时释放所有会话资源:
try: # 上传文件的代码块 sftp_client.put(...) upload_large_file(...) print(sftp_client.listdir()) except Exception as e: print(f"Upload failed: {str(e)}") finally: # 确保会话关闭,忽略关闭时的异常 try: sftp_client.close() except: pass try: ssh_client.close() except: pass
4. 服务器端排查
- 检查目标目录磁盘空间,确保能容纳2GB文件。
- 查看服务器日志(如OpenSSH的
/var/log/auth.log或/var/log/sftp.log),确认失败时的具体错误信息,排查是否存在文件大小限制、配额不足或资源耗尽记录。 - 调整服务器SFTP配置(如
sshd_config中的MaxSessions、MaxStartups参数),增加会话数上限,避免资源耗尽。 - 确认服务器是否有临时封禁机制,调整超时时间或添加白名单。
5. 任务计划优化
- 在任务计划程序中设置失败后重试机制,添加15分钟以上的重试间隔,避免短时间内频繁请求触发封禁。
- 验证脚本运行用户对共享驱动器的读取权限,防止大文件读取时出现权限问题。
内容的提问来源于stack exchange,提问作者andrea
相关产品推荐
相关产品推荐

