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 portbad 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 --rebasegit 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 cleanEACCES: 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 # 清除环境变量,避免冲突

# 设置 PATH(解决 SSH 非登录环境找不到命令的问题)
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

# 1. 强制切换到 main 分支(避免分支混乱)
git checkout main >> $LOG_FILE 2>&1

# 2. 拉取最新代码
echo "Pulling latest code..." >> $LOG_FILE
git pull $GIT_DIR main >> $LOG_FILE 2>&1

# 3. 彻底清理旧文件(避免残留)
echo "Cleaning old files..." >> $LOG_FILE
rm -rf public/ db.json .deploy_git/ node_modules/ package-lock.json >> $LOG_FILE 2>&1

# 4. 全新安装依赖(不使用镜像源,避免版本不一致)
echo "Installing dependencies..." >> $LOG_FILE
npm install >> $LOG_FILE 2>&1

# 5. 生成静态文件
echo "Generating static files..." >> $LOG_FILE
npx hexo clean >> $LOG_FILE 2>&1
npx hexo generate >> $LOG_FILE 2>&1

# 6. 复制到网站根目录
echo "Copying files to root..." >> $LOG_FILE
cp -rf public/* ./ >> $LOG_FILE 2>&1

# 7. 修复权限(只改权限,不改所有者,避免 Operation not permitted)
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 用户是否可读。

几乎踩遍了自动化部署可能遇到的所有典型问题!🚀