DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

rsync 经 SSH 报 protocol version mismatch:远端启动脚本输出污染协议

远端 Bash 启动脚本打印欢迎语时,rsync 的 SSH 协议流可能混入额外字节。用无输出命令定位,再把交互提示限制到交互 shell,保留远程任务需要的环境。

rsync 通过 SSH 连接远端,尚未正常传文件就报 protocol version mismatch -- is your shell clean?,并以协议不兼容的状态 2 退出。若临时移走远端 .bashrc 后错误消失,应检查启动脚本产生的输出,而不是继续删除整个配置文件或只调整 rsync 协议版本。

远端 shell 启动时打印欢迎语、状态信息或颜色控制字符,这些字节可能进入 rsync 用于协议通信的标准输出。rsync 接收到的开头不再是预期协议数据,才出现看起来像版本不兼容的报错。

本文针对经 SSH 运行远端 rsync、远端使用 Bash 的场景。相同报错也可能有真正的协议兼容或远端命令启动问题,必须先确认输出来源;仅有 .bashrc 文件本身并不会导致故障。

先检查一个本应没有输出的远端命令

使用发生故障时的同一 SSH 用户、主机、端口和认证设置,在空的本地诊断目录中保存输出。下面主机为占位值,/bin/true 需要在远端存在:

ssh operator@server.example.net /bin/true > remote-stdout.dat
ssh_status=$?
printf 'ssh status: %s\n' "$ssh_status"
wc -c < remote-stdout.dat

true 本身不输出内容。如果 SSH 正常完成且文件不是零字节,就有额外内容混入了远端标准输出。查看文件中是否有熟悉的欢迎语、路径提示或初始化消息,再沿对应脚本查找。含控制字符的输出不要直接当命令执行,诊断文件也不应作为公开日志上传。

这里不要添加 2>&1:SSH 的诊断信息通常写到标准错误,把两个流混到一起会妨碍判断。也不要为了“保持干净”将全部输出丢到 /dev/null,那只会隐藏证据。输出文件会覆盖同名文件,需使用专用诊断目录。

若 SSH 退出状态非零,即使文件为空也不能视为检查通过,应先处理认证失败、远端命令不存在或受限账户等错误。命令成功且输出为空,只能排除这次探测里的多余输出;rsync 专用包装命令、强制命令或不同运行环境仍可能另有输出。

只让交互提示在交互 Bash 中打印

Bash 在判断自己由 sshd 等远程机制非交互启动时,仍可能读取 .bashrc。因此,“没有打开交互终端”不等于“不会执行启动脚本”。按实际账户检查 .bashrc 及它加载的其他脚本,定位会输出文本或控制序列的语句。

修改前保存原配置,并保持一个可用管理会话。若只是想在人工打开 shell 时显示提示,可以将那几条输出语句放进交互条件中,而不跳过整个文件:

case $- in
    *i*)
        printf '%s\n' 'Interactive shell ready'
        ;;
esac

Bash 的 $- 包含 i 才表示交互模式。用这个条件包住原本的欢迎信息或终端设置;示例提示文字可替换。不要把检查登录 shell 的 login_shell 当成交互判断,登录与交互是两个不同属性。

有些默认 .bashrc 在非交互场景直接 return,但给现有文件顶部补一个全局提前返回前,必须确认后续配置是否还承担远程命令所需的 PATH 或环境设置。只约束有副作用的显示语句,通常能保留这类必要设置,避免消除输出后又变成找不到 rsync。

不要照搬“把所有内容搬到 .bash_profile”来处理。实际读取哪些文件取决于 shell 的启动方式,脚本间还可能相互加载。应修正已经确认的输出点,并用同一连接方式重新检查。

客户端重定向不能修复远端已经混入的字节

如果多余内容已经写进远端标准输出,给本地 rsync 命令加静默选项或重定向,不能从协议流里自动删掉这些字节。没有修改远端账户配置的权限时,需要由对应管理员修正启动脚本或远程命令包装层。

也不要为此强制 SSH 分配伪终端,或改用未规划的 rsync daemon 服务。传输机制与授权边界会随之变化,既没有定位输出来源,也可能引入新的运行条件。

如果探测没有额外输出,保留原报错,检查两端 rsync 是否能启动、实际版本与使用的远端命令。协议版本选项只能针对已确认的兼容需求使用,不能把欢迎语变成有效协议数据。

修复后先预演原同步范围

重新执行同一用户和连接参数下的无输出命令,确认 SSH 成功且输出文件为零字节。随后使用原同步路径和选项的预演模式检查计划变更,不因协议恢复就增加删除参数或扩大范围。

预演成功后再依照原有同步流程执行,并检查退出状态、目标内容和必要属性。不要仅凭欢迎语消失判定整次同步完成。若改动启动脚本导致其他远程任务缺少环境,应恢复事先保存的配置,再把修正缩小到实际输出语句;无需长期移除整份 .bashrc。