背景

作为一个技术博客作者,每次写完文章都要手动执行一系列命令来部署:

1
2
3
4
5
6
7
8
git add .
git commit -m "new post"
git push
ssh server
cd /path/to/blog
git pull
hexo clean && hexo generate
# 重启服务...

这个过程不仅繁琐,而且容易出错。更重要的是,每次部署都要手动操作,无法实现真正的持续集成

为了解决这个问题,我引入了 OpenClaw 作为自动化助手,配合 GitHub自动化部署脚本,实现了:

  • ✅ 本地写完文章后一键提交
  • ✅ GitHub 自动触发服务器拉取最新代码
  • ✅ 自动执行 Hexo 生成和部署
  • ✅ 性能优化(Gzip 压缩、图片优化、缓存策略)
  • ✅ 部署完成后自动通知

本文将详细介绍整个自动化部署流程的实现细节。


什么是 OpenClaw

OpenClaw 是一个开源的 AI 代理框架,能够:

  • 访问本地文件系统
  • 执行 Shell 命令
  • 控制浏览器
  • 管理 Git 仓库
  • 与外部服务(GitHub、QQ、飞书等)集成

简单来说,它就像一个住在你服务器上的智能助手,可以帮你自动完成各种重复性工作。

核心能力

能力 说明
文件操作 读写、编辑、创建文件
命令执行 运行任意 Shell 命令
Git 集成 自动拉取、提交、推送代码
定时任务 通过 cron 或 heartbeat 定期检查
消息通知 支持 QQ、Telegram、飞书等

自动化部署架构

1
2
3
4
5
6
7
8
9
10
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ 本地编辑 │────▶│ GitHub │────▶│ 服务器 │
│ (写文章) │ │ (代码仓库) │ │ (OpenClaw) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ Webhook │ 自动部署
▼ ▼
┌─────────────┐ ┌─────────────┐
│ 触发通知 │◀────│ 执行脚本 │
└─────────────┘ └─────────────┘

工作流程

  1. 本地写作:在本地编辑 Markdown 文章
  2. 提交推送git push 到 GitHub
  3. Webhook 触发:GitHub 通知服务器有新代码
  4. OpenClaw 执行:自动拉取代码并部署
  5. 性能优化:图片压缩、Gzip 启用
  6. 服务重启:Hexo 生成静态文件并重启服务
  7. 通知反馈:发送部署结果到 QQ/飞书

环境准备

服务器要求

  • Linux (Ubuntu/CentOS/Debian)
  • Node.js 18+
  • Git
  • OpenClaw

安装 OpenClaw

1
2
3
4
5
# 使用 npm 全局安装
npm install -g openclaw

# 初始化工作区
openclaw init

配置 GitHub SSH

1
2
3
4
5
6
# 生成 SSH 密钥
ssh-keygen -t ed25519 -C "your_email@example.com"

# 添加公钥到 GitHub
cat ~/.ssh/id_ed25519.pub
# 复制输出,添加到 GitHub Settings → SSH Keys

部署脚本实现

核心部署脚本 (deploy.sh)

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
54
#!/bin/bash
# 博客自动部署脚本

set -e

export PATH="/root/.nvm/versions/node/v22.22.0/bin:$PATH"

BLOG_DIR="/root/.openclaw/workspace/blog"
PUBLIC_DIR="$BLOG_DIR/public"
PID_FILE="/tmp/blog-server.pid"
PORT=8081
LOG_FILE="/var/log/blog-deploy.log"

log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

START_TIME=$(date +%s)
log "========== 开始部署 =========="

cd "$BLOG_DIR"

# 1. 拉取最新代码
log "拉取最新代码..."
git pull origin main

# 2. 清理并生成
log "清理旧文件..."
npx hexo clean

log "生成静态文件..."
npx hexo generate

# 3. 重启服务
log "重启博客服务..."
if [ -f "$PID_FILE" ]; then
OLD_PID=$(cat "$PID_FILE")
kill "$OLD_PID" 2>/dev/null || true
fi

fuser -k "$PORT/tcp" 2>/dev/null || true
sleep 1

cd "$PUBLIC_DIR"
nohup node server.js > /tmp/blog-server.log 2>&1 &
NEW_PID=$!
echo "$NEW_PID" > "$PID_FILE"

sleep 2
log "服务启动成功,PID: $NEW_PID"

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))
log "========== 部署完成 (耗时 ${DURATION}s) =========="

自动拉取脚本 (auto-deploy.sh)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# 定时检查更新并部署

LOG_FILE="/var/log/auto-deploy.log"
BLOG_DIR="/root/.openclaw/workspace/blog"

log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

cd "$BLOG_DIR"

git fetch origin main

LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)

if [ "$LOCAL" != "$REMOTE" ]; then
log "✅ 检测到更新,开始部署..."
/root/.openclaw/workspace/blog/deploy.sh
else
log "没有更新,跳过部署"
fi

GitHub Webhook 配置

创建 Webhook 服务

在服务器上创建 webhook-server.js

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
const http = require('http');
const { exec } = require('child_process');
const crypto = require('crypto');

const PORT = 9000;
const SECRET = 'your_webhook_secret';
const DEPLOY_SCRIPT = '/root/.openclaw/workspace/blog/deploy.sh';

const server = http.createServer((req, res) => {
if (req.method === 'POST' && req.url === '/webhook') {
const signature = req.headers['x-hub-signature-256'];
const body = req.body;

// 验证签名
const hmac = crypto.createHmac('sha256', SECRET);
const digest = 'sha256=' + hmac.update(body).digest('hex');

if (signature !== digest) {
res.writeHead(401);
res.end('Invalid signature');
return;
}

// 执行部署
exec(DEPLOY_SCRIPT, (error, stdout, stderr) => {
if (error) {
console.error(`部署失败:${error}`);
return;
}
console.log(`部署成功:${stdout}`);
});

res.writeHead(200);
res.end('Deployment triggered');
}
});

server.listen(PORT, () => {
console.log(`Webhook 服务器运行在端口 ${PORT}`);
});

启动 Webhook 服务

1
2
3
4
5
# 使用 PM2 管理
npm install -g pm2
pm2 start webhook-server.js --name blog-webhook
pm2 startup
pm2 save

GitHub 配置

  1. 打开 GitHub 仓库 → Settings → Webhooks
  2. 点击 “Add webhook”
  3. 填写:
    • Payload URL: http://your-server:9000/webhook
    • Content type: application/json
    • Secret: 与脚本中一致
    • Events: 选择 “Just the push event”
  4. 点击 “Add webhook”

性能优化

1. Gzip 压缩

在 Nginx 配置中启用 Gzip:

1
2
3
4
5
6
7
8
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_types text/plain text/css text/xml text/javascript
application/javascript application/xml+rss
application/json;
gzip_comp_level 6;

效果:HTML 文件从 40KB 压缩到 10KB,压缩比 75%

2. 图片优化

创建图片压缩脚本 (compress-images.sh):

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
# 使用 tinypng 压缩图片

API_KEY="your_tinypng_api_key"

for img in source/_posts/*.jpg; do
curl -X POST \
-H "Authorization: Basic $API_KEY" \
-F "file=@$img" \
https://api.tinify.com/shrink \
-o "${img%.jpg}-compressed.jpg"
done

效果:图片平均减小 60-70%

3. 浏览器缓存

1
2
3
4
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}

4. 静态资源 CDN

将图片、CSS、JS 等静态资源托管到 CDN:

  • 七牛云
  • 阿里云 OSS
  • Cloudflare

OpenClaw 自动化流程

配置 Heartbeat

HEARTBEAT.md 中添加定期检查任务:

1
2
3
4
# 每 30 分钟检查一次博客部署状态
- 检查 GitHub 是否有新提交
- 检查服务是否正常运行
- 检查磁盘空间

OpenClaw 自动执行

OpenClaw 会定期:

  1. 检查 GitHub 仓库是否有新代码
  2. 如果有更新,自动执行 git pull
  3. 运行 hexo generate 生成静态文件
  4. 重启博客服务
  5. 发送部署通知

消息通知

部署完成后,OpenClaw 会自动发送通知:

1
2
3
4
✅ 博客部署成功
📝 提交:feat: 新增文章
⏱️ 耗时:15s
🔗 访问:http://your-blog.com

实际使用流程

写作并发布

1
2
3
4
5
6
7
8
9
10
# 1. 在本地创建新文章
hexo new post "我的新文章"

# 2. 编辑文章
vim source/_posts/我的新文章.md

# 3. 提交并推送
git add .
git commit -m "new: 我的新文章"
git push origin main

自动部署

推送后,整个过程自动进行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GitHub 接收 push

触发 Webhook

OpenClaw 执行部署脚本

git pull 拉取最新代码

hexo clean && hexo generate

重启博客服务

发送 QQ/飞书通知

✅ 部署完成!

全程无需人工干预,通常 15-30 秒 即可完成部署。


监控与日志

查看部署日志

1
2
3
4
5
# 实时查看部署日志
tail -f /var/log/blog-deploy.log

# 查看最近的部署记录
grep "部署完成" /var/log/blog-deploy.log | tail -10

服务状态检查

1
2
3
4
5
6
7
8
# 检查服务是否运行
ps aux | grep blog-server

# 检查端口占用
netstat -tlnp | grep 8081

# 检查 PM2 状态
pm2 status

遇到的问题与解决方案

问题 1:Webhook 不触发

原因:服务器防火墙阻止了 9000 端口

解决

1
2
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --reload

问题 2:部署后页面未更新

原因:浏览器缓存

解决

  • 强制刷新:Ctrl + Shift + R
  • 或在 Nginx 中配置缓存策略

问题 3:图片加载慢

原因:图片未压缩

解决

  • 使用 compress-images.sh 批量压缩
  • 或配置 CDN 加速

总结

通过引入 OpenClaw 和自动化部署脚本,博客部署流程从手动 10+ 步骤简化为一键推送

对比项 手动部署 自动化部署
步骤数 10+ 1
耗时 5-10 分钟 15-30 秒
出错概率 极低
需要值守

核心优势

  1. 省时省力:写完文章直接 push,剩下的交给 OpenClaw
  2. 可靠性高:自动化脚本减少人为错误
  3. 性能优化:Gzip、图片压缩、缓存策略自动应用
  4. 可追溯:所有部署记录都有日志
  5. 可扩展:轻松添加新功能(如自动备份、监控告警)

未来规划

  • 添加自动备份功能
  • 集成性能监控(Lighthouse CI)
  • 支持多环境部署(测试/生产)
  • 添加回滚机制

参考资源


如果你觉得这篇文章有帮助,欢迎 star 我的博客项目!