Gerrit 下载 commit-msg 报 subsystem request failed on channel 0
OpenSSH 9.0 起 scp 默认使用 SFTP,Gerrit 的 SCP hook 下载端点可能拒绝子系统请求。确认失败阶段后限定使用 -O,或改用实例公布的 HTTPS 下载入口。
从 Gerrit 下载 hooks/commit-msg,命令连接了正确的 SSH 端口,却报:
subsystem request failed on channel 0
scp: Connection closed
如果此前同样的下载命令可用,而现在客户端使用 OpenSSH 9.0 或更高版本,应核对传输协议。OpenSSH 9.0 从 2022 年 4 月 8 日发布起,让 scp 默认使用 SFTP;支持旧 SCP hook 下载的服务,并不一定提供 SFTP 子系统。
本文处理 Gerrit SSH 服务不支持当前客户端所请求的 SFTP、但支持 SCP hook 下载的场景。相同错误也可能出现在普通 SSH 服务器的 SFTP 配置故障中,不能只凭这两行就认定所有服务器都应改用旧协议。
区分连接、认证与子系统请求
先核对下载说明中的账户、主机、端口和路径。Gerrit 常见 SSH 端口为 29418,实际部署可以不同;不要把它误换成系统 SSH 的 22,两者可能是不同服务。
scp -v 的详细日志可帮助分辨失败发生在哪一步。如果已经完成认证,随后请求 sftp 子系统被拒绝,才符合这里的分支。若日志是连接超时、Permission denied 或主机密钥变化,应分别处理连接、认证或主机身份,添加 -O 不会绕过这些检查。
确认版本时检查实际调用的 scp 所属 OpenSSH 安装和本机手册。不同软件可能携带自己的客户端;另一个目录下的 SSH 版本不能单独代表当前使用的程序。分享详细日志前,清理账号、内部地址和本地路径。
对这次 Gerrit 下载显式使用旧 SCP
已确认该 Gerrit 端点支持 SCP 下载时,可给这一次命令加大写字母 -O。在专用空目录中先下载成待检查文件,避免直接覆盖仓库里已有的 hook:
scp -O -p -P 29418 \
developer@review.example.com:hooks/commit-msg \
./commit-msg.download
developer、域名和端口都需要替换成服务提供的实际值。本地目标必须不存在,或已确认可以覆盖。大写 -O 选择旧 SCP 协议,大写 -P 指定端口,小写 -p 保留时间和文件模式;它们不能相互替代,也不是数字 0。
该选项仍通过 SSH 连接传输,不需要关闭主机身份检查。旧 SCP 对远端文件名和 shell 特殊字符的处理与 SFTP 不同;这里使用固定的 hooks/commit-msg 路径,不要把任意外部输入或未经检查的通配符拼进去。
不用把所有 scp 调用都加上 -O。限定在确实不提供 SFTP 的 Gerrit 下载端点;若服务以后支持 SFTP,再用默认协议验证这项兼容参数是否仍必要。客户端不认识 -O 时,先检查实际实现与版本,不能假定所有名为 scp 的程序都支持同组选项。
Gerrit 提供 HTTPS 下载时,也可以使用它
如果实例公布了 HTTPS hook 下载入口,可以直接获取同一脚本。以下地址仍是占位值,应采用项目实际的 Gerrit 基础地址;有部署在子路径下的实例,不能丢掉该前缀:
curl --fail --location \
--proto-redir '=https' \
--output ./commit-msg.download \
'https://review.example.com/tools/hooks/commit-msg'
在空目录使用此命令,确认最终接收地址符合项目说明。HTTPS 下载绕开了 Gerrit SSH 端口的文件传输协议要求,并不意味着所有项目都允许匿名下载,或任意登录页面都能充当 hook。
--fail 能处理通常的 HTTP 错误状态,但返回 200 的登录 HTML 仍可能保存下来。因此下载结束后,应检查文件确实是预期的 commit-msg 脚本,而不是错误页、登录页或重定向说明。不要直接将下载内容交给 shell 执行。
下载成功后再安装,保留原 hook
scp 退出状态为 0 或 curl 完成下载,只表示取得了响应或文件。还要核对来源、文件内容和项目的 hook 安装方式。commit-msg 会在创建提交等操作中被 Git 调用,未经检查的内容不应直接安装到生效位置。
如果目标仓库已有自定义 commit-msg,先保存它并确认是否需要保留原逻辑;不要用下载解决方案顺手覆盖。按仓库实际的 hooks 配置安装,并确保需要运行的脚本具有执行权限,再在测试仓库或可回退的提交中核对预期行为。取得脚本和成功生成 Gerrit 所需的提交标识,是两个不同的验收步骤。
这次错误发生在下载阶段,不需要修改系统 sshd 配置、放宽认证、重建仓库或强推提交。若安装后影响了原有 hook 行为,恢复事先保存的版本;若只是测试下载,删除本次新增的待检查文件即可,保留原仓库内容。


