通过SSH运行rsync时,终端返回protocol version mismatch -- is your shell clean?。这句话容易让人先去更换rsync版本,但官方诊断说明,更常见的原因是远端Shell在协议数据前输出了欢迎语、调试内容或命令结果。
rsync需要一条干净的二进制数据流,任何额外字符都可能破坏握手。

为什么会出现协议不匹配
rsync通过远程Shell启动另一端rsync进程,随后双方在同一连接上交换协议数据。若.profile、.bashrc、.cshrc、登录横幅或SSH强制命令向标准输出写入文本,接收端读到的第一个字节就不再是rsync协议。
错误名称包含version mismatch,不代表两端版本一定无法协商。正常版本差异会由rsync自动协商共同协议。
用官方方法检查Shell是否干净
在本地执行ssh remotehost /bin/true > out.dat,再检查out.dat大小。rsync官方手册指出,正常结果应为零字节;若文件包含欢迎语、调试echo或命令报错,就已经找到污染标准输出的线索。
检查文件内容前先确认没有敏感环境变量或密钥被启动脚本意外输出。
修正启动脚本的输出条件
把只供交互终端显示的提示语放进交互Shell判断中,例如Bash可根据$-是否包含i决定是否输出。检查脚本中无条件执行的echo、printf、命令调试和失败信息;需要保留诊断时应写入日志或标准错误,并评估远程命令兼容性。
不要直接清空整个profile或rc文件。它可能同时承担PATH和运行环境初始化。
何时再核对rsync版本和路径
Shell输出恢复为零字节后,再运行rsync --version并通过ssh remotehost command -v rsync确认远端实际执行文件。若存在多个安装版本,可用--rsync-path明确远端程序路径,但不要把它用于执行不可信的拼接命令。
只有确认数据流干净后,版本与程序路径检查才有诊断价值。
修复后的验收方法
重新运行零字节测试,再以--dry-run --itemize-changes验证rsync握手和文件清单,最后执行小规模真实同步。可在萤光云或LightNode的测试VPS验证非交互Shell。验收标准是远程true无标准输出、rsync能协商协议、退出码为0且启动脚本在交互登录时仍正常。
FAQ
问:可以直接使用–protocol强制旧版本吗?答:不建议。官方说明双方会自动协商,强制降级不能修复被文本污染的数据流。
问:SSH登录时没有欢迎语就一定没问题吗?答:不一定,交互登录与远程命令会读取不同启动脚本,必须按官方零字节方法测试。
问:把提示写到标准错误就完全安全吗?答:rsync主要协议走标准输入输出,但远程Shell与封装脚本的重定向可能不同,仍应实际验证。
问:MOTD会导致该错误吗?答:取决于SSH与PAM配置是否在非交互远程命令中输出它,应通过抓取结果确认。
问:为什么只在定时脚本中出现?答:定时环境的用户、Shell、PATH和启动文件可能不同,需用同一身份复现。
温馨提示
温馨提示:远程命令账户的启动脚本应保持安静、可重复,并把人类可读提示限制在交互会话。升级Shell配置后可加入零字节检查。


