SFTP上传明明显示成功,但远程文件纹丝不动?问题很可能出在这几个地方:远程目录缺少写和执行权限、SSH的StrictModes在背后作梗、preserve_modification_times在特定环境下引发协议冲突,或者upload_on_sa ve的路径映射规则没对上。

remote_path目录缺w/x权限导致静默失败
明明提示“Upload completed”,远程文件却纹丝未变——十有八九是远程目录的权限在使绊子。SFTP上传可不是简单覆盖文件那么简单,它背后有一整套流程:创建临时文件、重命名、删除旧文件。这一步一步,都依赖于目录的w(写)和x(执行/进入)权限。缺了哪个,都可能导致静默失败。
- 先登录服务器跑一下
ls -ld /var/www/html:如果看到dr-xr-xr-x,说明目录只读不可写;正确姿势是drwxr-xr-x(注意别手滑改成777) - 用
touch /var/www/html/test.tmp && rm /var/www/html/test.tmp实测一下写权限——如果连这个都失败,那问题不在插件,而是系统级别的拦截(SELinux或AppArmor也可能掺一脚) - 再看看父目录属主:
ls -ld /var/www。如果显示root:root,那普通用户根本没法在里面建子目录。解决方案是用sudo chown -R把属主改对,Ubuntu上改成$USER:www-data,CentOS上改成$USER:nginx
SSH StrictModes开启引发只读降级
服务器/etc/ssh/sshd_config里StrictModes on(这是OpenSSH的默认设置)的时候,只要~/.ssh/authorized_keys的权限不是600,或者属主不对,SSH连接就会悄悄降级为密码认证。而SFTP插件如果没配password字段,结果就是静默只读——不报错,也不上传,让你摸不着头脑。
- 确认密钥文件权限:
ls -l ~/.ssh/authorized_keys,必须是-rw-------,而且属主为你当前用户 - 修复命令:
chmod 600 ~/.ssh/authorized_keys && chown $USER:$USER ~/.ssh/authorized_keys - 改完记得重启sshd:
sudo systemctl restart sshd(Linux)或sudo service ssh restart
sftp-config.json里preserve_modification_times设错
在NFS挂载、Docker容器卷或者某些云存储后端上,preserve_modification_times: true(默认值)会导致上传后时间戳同步失败,进而触发SFTP协议层拒绝写入——表现就是文件内容没更新,日志里可能只有个Failure,没有具体错误信息。
- 直接在
sftp-config.json根层级加一行:"preserve_modification_times": false - 这个开关只影响文件时间戳,不影响内容同步。关掉之后,绝大多数NFS/容器场景就能正常上传了
- 别和
default_permissions搞混:default_permissions控制新建文件权限(比如"644"),跟时间戳无关
upload_on_sa ve生效但被路径映射规则过滤
upload_on_sa ve: true不是全局开关——它只对“当前文件路径匹配remote_path映射规则”的文件生效。你改了/src/js/app.js,但remote_path设的是"/var/www/html/",那它根本不会触发上传,插件连试都不试。
- 确保本地项目根目录结构和远程路径对齐。比如远程是
/var/www/html/js/app.js,本地就得是html/js/app.js - 或者用
file_regex显式声明匹配规则,例如:"file_regex": "^(src|js|css)/.*.(js|css|html)$" - 检查是否误启了
sync_down_on_open: true——它会在打开文件时从远程拉取,覆盖本地未保存修改,造成“改了又变回去”的假象
实际调试中,最容易踩坑的是整条路径的x权限和StrictModes的连锁反应——它们不报错,只沉默拒绝。建议你先跑一遍touch + rm测试,再检查authorized_keys权限,比反复折腾配置要高效得多。