Git钩子在宝塔静默失败主因是SSH密钥未配对或目录所有权错乱:钩子以root等用户执行导致网站目录属主为root:root,Nginx拒绝读取;须用绝对路径调用命令、显式设置PATH、chown -R www:www网站目录并确保www用户有git执行权限。

Git钩子在宝塔上静默失败,90%不是代码问题,而是SSH密钥没配对或目录所有权错乱。 宝塔本身不托管 Git 服务,所有“自动部署”都依赖你手动搭的 bare 仓库 + 钩子脚本,而这两处最容易卡在权限和环境上。
post-receive 钩子执行但网站目录没更新?先查 www 用户能不能写入
宝塔网站默认由 www 用户运行,但 SSH 推送时钩子常以 root 或你的登录用户身份执行。一旦钩子用 git checkout -f 写进 /www/wwwroot/my-site,文件属主就变成 root:root,Nginx 直接拒绝读取——页面空白或 403 错误。
- 钩子脚本里必须加这行:
chown -R www:www /www/wwwroot/my-site - 别只改网站目录,bare 仓库目录也要给
www读权限:chmod -R 755 /www/wwwroot/my-site.git - 检查实际属主:
ls -ld /www/wwwroot/my-site,输出第一列应为drwxr-xr-x 1 www www - 如果看到
root root,说明钩子根本没跑完或chown被跳过了(比如前面 git 命令失败导致脚本提前退出)
remote: fatal: unable to fork 或 hook 没反应?SSH 密钥和解释器路径是关键
Git over SSH 推送时,服务器端执行的是 shell 环境下的钩子。但 www 用户通常没配置 shell、没加载 PATH,更不会读取你的 ~/.bashrc,所以常见报错不是“找不到 git”,而是“fork 失败”或“command not found”。
- 钩子第一行必须写死解释器:
#!/bin/bash(别用#!/usr/bin/env bash) - 所有命令用绝对路径:
/usr/bin/git --work-tree=... checkout -f,别信git能自动找到 - 确认
www用户能执行git:sudo -u www /usr/bin/git --version,如果报错,说明www的 PATH 缺失,得在钩子里加:export PATH="/usr/bin:/bin:$PATH" - SSH 密钥要配到推送用户的
~/.ssh/authorized_keys里,且该用户必须有权限读 bare 仓库(chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys)
本地 git push 卡住或报 “Connection refused”?检查裸仓库路径和 SSH 连接方式
很多人把远程地址写成 user@ip:/www/wwwroot/my-site.git,结果推送失败。这不是 Git 报错,是 SSH 层面连不上或路径不可达。
- 确保裸仓库路径是绝对路径,且
user对该路径有读写权(ls -ld /www/wwwroot/my-site.git应显示drwxr-xr-x或更宽松) - 测试 SSH 是否通:
ssh user@ip 'ls -l /www/wwwroot/my-site.git',不通就先解决 SSH 登录问题(密钥、防火墙、sshd 配置) - 别用密码登录——Git 推送不支持交互式输密码,必须走密钥认证
- 如果服务器开了宝塔防火墙,确认放行了 SSH 端口(默认 22),且没限制该 IP 的连接数
真正难调试的从来不是钩子逻辑,而是谁在什么环境下、以什么权限、调用了哪个路径的 git。每次修改后,务必用 ssh user@ip 'bash -x /www/wwwroot/my-site.git/hooks/post-receive' 手动执行一次钩子,看真实输出——静默失败永远比报错更危险。


















