使用ssh2_scp_send()函数无法传输超过10KB文件的问题求助
SSH2 SCP传输超过10KB文件失败的解决办法
遇到这种小文件正常、大文件传输失败的情况,大概率是SCP协议本身对大文件的支持局限,或者是SSH连接超时、服务器配置限制导致的。我给你整理几个靠谱的排查和解决思路:
一、先排查SSH服务器端的配置限制
登录到你的目标服务器,检查/etc/ssh/sshd_config文件,看看有没有可能导致传输中断的设置:
- 确保开启了
TCPKeepAlive yes,这个选项能防止长时间传输时连接被服务器主动断开 - 调整心跳相关参数,添加或修改:
意思是服务器每30秒给客户端发一次心跳,连续10次没收到回应才断开连接,避免大文件传输时超时ClientAliveInterval 30 ClientAliveCountMax 10 - 确认没有设置
MaxPacketSize这类限制单包大小的参数(默认是没有的)
修改完配置后,记得重启SSH服务生效:
sudo systemctl restart sshd # 适用于systemd系统(比如Ubuntu 16.04+、CentOS 7+) # 或者用 service ssh restart (老版本系统)
二、改用SFTP协议传输(推荐)
PHP的ssh2_scp_send函数对大文件的支持确实不太友好,换成SFTP协议分块传输会稳定很多。给你改好的代码示例:
$connection = ssh2_connect("MyHost", port); if(ssh2_auth_password($connection, 'user', 'password')){ // 初始化SFTP会话 $sftp = ssh2_sftp($connection); if($sftp){ // 打开远程文件的写入句柄(注意路径格式是ssh2.sftp://{$sftp}/远程路径) $remoteFile = fopen("ssh2.sftp://{$sftp}/test.csv", 'w'); // 打开本地文件的读取句柄 $localFile = fopen("/cloud/domains/live/domains/domain.com/http/test.csv", 'r'); if($remoteFile && $localFile){ // 分块读取写入,每次4KB,避免一次性加载大文件到内存 while(!feof($localFile)){ fwrite($remoteFile, fread($localFile, 4096)); } echo "大文件传输成功!"; // 记得关闭文件句柄 fclose($localFile); fclose($remoteFile); } else { echo "无法打开本地或远程文件句柄,请检查权限!"; } } else { echo "SFTP会话初始化失败,请确认服务器支持SFTP!"; } } else { echo "SSH连接失败,请检查主机、端口、账号密码!"; } // 关闭连接 ssh2_exec($connection, 'exit');
三、调整PHP的超时设置
如果大文件传输需要较长时间,PHP的默认超时时间可能会中断传输:
- 打开
php.ini文件,找到以下两个参数:max_execution_time = 300 # 把默认的30改成300(5分钟),根据文件大小调整 default_socket_timeout = 300 # 同样调大 - 保存后重启PHP服务(比如
sudo systemctl restart php-fpm)
四、额外检查项
- 确认远程目标目录(比如你这里的
/目录)有足够的写入权限,虽然小文件能传,但大文件写入时可能涉及临时空间的问题,也可以先试试传到/tmp目录测试 - 检查本地文件的读权限,确保PHP进程能读取到
test.csv
内容的提问来源于stack exchange,提问作者hardik
相关产品推荐
相关产品推荐

