Hexo 自动化部署避坑指南:从零到一的实战总结
一、核心认知:理顺三个仓库的关系
这是所有问题的根基,理解它,就理解了 80% 的部署逻辑。
| 位置 |
角色 |
内容 |
操作者 |
| 本地仓库 |
源码工作区 |
文章、主题、配置 (source/, themes/, _config.yml) |
开发者 |
| 服务器裸仓库 |
中央版本库 |
仅存储 Git 历史 (/home/git/repos/xxx.git) |
git push 的目标 |
| 服务器网站目录 |
生产环境工作区 |
可被 Nginx 访问的静态文件 (/www/wwwroot/xxx) |
Git 钩子自动部署的目标 |
核心逻辑:git push → 裸仓库触发钩子 → 钩子拉取代码到网站目录 → 构建并生成静态文件。
二、避坑清单:按问题类型分类
🚨 1. SSH 与 Git 配置坑
| 问题现象 |
根本原因 |
解决方法 |
Bad port 或 bad configuration options |
本地的 ~/.ssh/config 或 .git/config 格式错误。 |
Port 后面只跟数字,HostName 只跟 IP,不要混写。 |
Permission denied (publickey) |
服务器未添加本地公钥,或 ~/.ssh/authorized_keys 权限不对。 |
确保 authorized_keys 权限为 600,.ssh 目录权限为 700。 |
fatal: detected dubious ownership |
Git 检测到仓库所有者与当前用户不匹配。 |
在服务器上执行 git config --global --add safe.directory /path/to/repo。 |
🚨 2. 分支与钩子触发坑(你这次遇到的核心问题)
| 问题现象 |
根本原因 |
解决方法 |
git push 成功但钩子未触发 |
钩子文件没有执行权限,或钩子内有 Windows 换行符 (\r\n)。 |
chmod +x post-receive;用 dos2unix 转换格式。 |
git push 后网站未更新 |
本地推送的是 main,但网站目录在 master 分支。 |
统一分支:git checkout main,并修改钩子拉取 main。 |
git push 显示 rejected |
本地与远程历史出现分歧(例如混用了 hexo d)。 |
用 git pull --rebase 或 git push --force(谨慎使用)。 |
钩子内 su: Authentication failure |
钩子非交互式执行,无法提供密码。 |
移除钩子中的 su 命令,让钩子直接以 git 用户身份运行。 |
🚨 3. 环境与依赖安装坑
| 问题现象 |
根本原因 |
解决方法 |
hexo: command not found |
钩子执行环境缺少 PATH 变量(SSH 非登录 Shell)。 |
在钩子开头显式设置 PATH,或使用 npx hexo。 |
Failed to @extend ".fontawesomeIcon" |
npm install 使用了镜像源(--registry),导致 Stylus 或主题依赖版本不一致。 |
在钩子中去掉 --registry 参数,使用系统默认源。 |
npm install 后报错 |
node_modules 损坏或缓存导致。 |
在钩子中先 rm -rf node_modules package-lock.json,再 npm install。 |
| 本地安装插件后服务器无效 |
只在服务器上安装了插件,但未更新 package.json。 |
**永远在本地执行 npm install --save**,然后提交 package.json。 |
🚨 4. 文件与目录权限坑(最频繁且最隐蔽)
| 问题现象 |
根本原因 |
解决方法 |
chown: Operation not permitted |
钩子以 git 用户执行 chown,但只有 root 能更改所有者。 |
在钩子中**只使用 chmod**,不修改所有者。 |
403 Forbidden |
Nginx 用户(如 www-data)无法读取网站目录。 |
确保目录权限为 755,文件权限为 644。或在钩子中修复权限。 |
hexo clean 报 EACCES: permission denied |
public/ 下有 root 创建的文件,git 用户无法删除。 |
用 root 执行 chown -R git:git,或手动 rm -rf public/。 |
.user.ini 无法删除/修改 |
文件被 chattr +i 锁定。 |
用 chattr -i .user.ini 解除锁定。 |
🚨 5. Nginx 与 Web 服务坑
| 问题现象 |
根本原因 |
解决方法 |
nginx: [emerg] unknown directive |
Nginx 配置文件有语法错误(缺少分号、括号不匹配)。 |
每次修改配置后,执行 nginx -t 检查语法。 |
systemctl restart nginx 失败 |
已有 Nginx 进程在运行,或 PID 文件冲突。 |
先 pkill -9 nginx,再 systemctl start nginx。 |
| 网站显示旧内容 |
浏览器强缓存。 |
强制刷新 Ctrl+F5,或清空浏览器缓存。 |
🚨 6. 链接与 URL 配置坑
| 问题现象 |
根本原因 |
解决方法 |
| 分类/标签链接包含旧路径 |
_config.yml 中的 root 配置错误(如 /project/)。 |
确保 root: /,且 url 为完整域名。 |
| 中文标题文章显示空白或 404 |
Hexo 对中文文件名支持不稳定。 |
在文章 Front-matter 中添加 slug: english-name 固定英文 URL。 |
hello-world 日期变成了推送日期 |
Front-matter 缺少 date 字段,使用文件创建时间。 |
所有文章都显式添加 date 字段。 |
三、最终稳定版钩子脚本模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #!/bin/bash
LOG_FILE="/tmp/hexo-deploy.log" echo "========================================" >> $LOG_FILE echo "Deploy started at $(date)" >> $LOG_FILE
WEB_DIR="/www/wwwroot/www.xxx.xxx" GIT_DIR="/home/git/repos/xxx.git"
cd $WEB_DIR || { echo "Failed to enter $WEB_DIR" >> $LOG_FILE; exit 1; } unset GIT_DIR
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$HOME/.nvm/versions/node/v18.20.0/bin:$PATH"
echo "Node version: $(node -v)" >> $LOG_FILE echo "NPM version: $(npm -v)" >> $LOG_FILE echo "Current user: $(whoami)" >> $LOG_FILE
git checkout main >> $LOG_FILE 2>&1
echo "Pulling latest code..." >> $LOG_FILE git pull $GIT_DIR main >> $LOG_FILE 2>&1
echo "Cleaning old files..." >> $LOG_FILE rm -rf public/ db.json .deploy_git/ node_modules/ package-lock.json >> $LOG_FILE 2>&1
echo "Installing dependencies..." >> $LOG_FILE npm install >> $LOG_FILE 2>&1
echo "Generating static files..." >> $LOG_FILE npx hexo clean >> $LOG_FILE 2>&1 npx hexo generate >> $LOG_FILE 2>&1
echo "Copying files to root..." >> $LOG_FILE cp -rf public/* ./ >> $LOG_FILE 2>&1
echo "Fixing permissions..." >> $LOG_FILE find $WEB_DIR -type d -exec chmod 755 {} \; 2>/dev/null find $WEB_DIR -type f -exec chmod 644 {} \; 2>/dev/null
echo "Deploy finished successfully at $(date)" >> $LOG_FILE
|
四、最后建议:日常维护清单
| 操作 |
注意事项 |
| 写新文章 |
确保 Front-matter 包含 date 字段,中文标题建议加 slug。 |
| 安装插件 |
在本地执行 npm install --save,然后提交 package.json。 |
| 修改主题 |
在本地修改,测试无误后提交。不要在服务器上直接改。 |
| 修改 Nginx |
修改后先 nginx -t 测试,再 systemctl reload nginx。 |
| 查看日志 |
定期检查 /tmp/hexo-deploy.log,异常时第一时间定位。 |
| 解决 403 |
检查网站目录权限是否为 755/644,以及 Nginx 用户是否可读。 |
几乎踩遍了自动化部署可能遇到的所有典型问题!🚀