Amazon Linux 2中curl通过SFTP下载大文件时返回退出码18,添加strace到sshd后问题消失
Amazon Linux 2中curl通过SFTP下载大文件时返回退出码18,添加strace到sshd后问题消失
看起来你遇到的是典型的**时序竞争条件(race condition)**问题,结合你提供的日志和现象,我来拆解下问题根源和可行的解决方向:
首先先锚定几个关键线索:
- 小文件(<120KB)下载正常,大文件到~150KB左右就触发退出码18,提示有剩余字节未读
- 原生
sftp命令的get操作完全正常,sftp-server日志也明确显示已经把所有文件数据发送完毕,甚至返回了EOF信号,但curl这边却没正确识别 - 给sshd加strace后问题消失——这是最核心的提示:strace会给进程添加额外的执行延迟,刚好“填平”了原本的时序缺口
问题根源分析
这种现象几乎可以确定是curl的SFTP客户端与Amazon Linux 2自带的openssh-server之间存在版本兼容性的竞争bug:
- 没有strace时,sshd/sftp-server发送数据和EOF的速度过快,curl的SFTP解析逻辑还没处理完前面的数据包,就收到了连接关闭的信号,错误判定为“连接提前关闭”,返回退出码18
- 加上strace后,进程执行被放慢,curl有足够的时间处理完所有数据并正确识别sftp-server发送的EOF,因此下载能正常完成
具体排查和解决步骤
1. 优先更新软件包(最有效)
这类时序bug通常会在官方后续补丁中修复,先检查当前curl和openssh-server的版本,然后更新到最新:
# 查看版本 curl --version rpm -q openssh-server # 更新并重启sshd sudo yum update curl openssh-server -y sudo systemctl restart sshd
更新后再测试curl的SFTP下载,大概率能直接解决问题。
2. 调整curl的SFTP参数(临时 workaround)
如果暂时无法更新,可以尝试调整curl的缓冲区或SFTP相关参数,强制改变数据处理时序:
- 调整缓冲区大小,和sftp-server的默认块大小匹配(比如16KB):
curl -u testuser:12345 -o /tmp/testfile --buffer-size 16384 sftp://127.0.0.1/home/testuser/testfile
- 强制curl使用更保守的SFTP文件状态校验:
curl -u testuser:12345 -o /tmp/testfile --sftp-use-fstat sftp://127.0.0.1/home/testuser/testfile
3. 修改sshd配置(调整传输时序)
也可以通过调整sshd的行为,给传输增加轻微延迟,避开竞争条件:
编辑/etc/ssh/sshd_config,修改或添加以下配置:
# 给sftp-server添加日志级别,增加轻微延迟 Subsystem sftp /usr/libexec/openssh/sftp-server -l INFO # 定期发送心跳包,保持连接活跃并调整时序 ClientAliveInterval 5 ClientAliveCountMax 3
然后重启sshd:
sudo systemctl restart sshd
4. 深入排查(如果需要定位具体原因)
如果上面的方法都没用,可以生成更详细的curl协议跟踪日志,确认curl是否收到了EOF信号:
curl -vvv --trace-ascii /tmp/curl_sftp_trace.log -u testuser:12345 -o /tmp/testfile sftp://127.0.0.1/home/testuser/testfile
查看/tmp/curl_sftp_trace.log的最后几行,如果curl没收到sftp-server发送的SSH_FX_EOF状态,说明是TCP层的时序问题;如果收到了但没处理,那就是curl的SFTP客户端bug,必须升级curl。
总结
最快捷的解决方法是更新curl和openssh-server到最新版本,官方补丁通常会修复这类版本相关的竞争bug。如果无法更新,调整缓冲区大小或sshd的心跳配置也能临时解决问题。
备注:内容来源于stack exchange,提问作者GP92
相关产品推荐
相关产品推荐

