从一键脚本到全自动部署

起点:手动操作

最开始更新博客要走三步:

  1. 本地 hexo generate 生成静态文件
  2. scp 上传到 ECS 服务器
  3. SSH 上去 docker compose restart nginx

后来写了个 deploy-blog.sh 把三步合成一条命令,已经方便了很多。但还是得手动执行

真正的自动化是什么?push 代码,剩下的全自动

这就是今天要搞的——GitHub Actions CI/CD


什么是 CI/CD

CI = 持续集成(Continuous Integration),代码 push 上去自动构建
CD = 持续部署(Continuous Deployment),构建完自动部署到服务器

一个典型的流程:

1
2
3
4
5
6
7
8
9
push 代码到 GitHub

GitHub Actions 自动触发

检出代码 → 安装依赖 → 生成静态文件

scp 上传到 ECS → SSH 重启 Nginx

博客更新完成 ✅

你只需要 git push,剩下的机器帮你做。


实现步骤

1. 把博客源码托管到 GitHub

之前博客只有生成的静态文件在 GitHub Pages 上。现在把包括 Markdown、主题、配置在内的完整源码单独建一个仓库 blog-source

1
2
3
4
5
6
cd ~/my-blog
git init
git add .
git commit -m "博客源码"
git remote add origin https://github.com/Bingsv/blog-source.git
git push

2. 配置 Secrets

GitHub Actions 的构建机器需要 SSH 连接你的 ECS。但密钥不能写在代码里公开,要用 GitHub Secrets:

仓库 → Settings → Secrets and variables → Actions → 添加三个 Secret:

Secret 名
ECS_HOST 服务器 IP
ECS_USER SSH 用户名
SSH_KEY SSH 私钥完整内容

3. 编写工作流文件

在项目里创建 .github/workflows/deploy.yml

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
name: 自动部署博客到 ECS

on:
push:
branches: [master] # push 到 master 就触发

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4

- name: 安装 Node.js
uses: actions/setup-node@v4
with:
node-version: '22'

- name: 安装依赖
run: npm ci

- name: 生成静态文件
run: npx hexo generate

- name: 部署到 ECS
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
scp -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key \
-r public/* ${{ secrets.ECS_USER }}@${{ secrets.ECS_HOST }}:~/blog-static/
ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key \
${{ secrets.ECS_USER }}@${{ secrets.ECS_HOST }} \
"cd ~/blog-compose && docker compose restart nginx"

踩过的坑

坑 1:hexo 命令找不到

hexo generate 在 Actions 机器上报 Permission deniedcommand not found

原因:本地装了 hexo-cli 全局包,但 Actions 机器上没有。

解决:用 npx hexo generate 并在项目里 npm install --save-dev hexo-cli

坑 2:第三方 Action 版本号错误

easingthemes/ssh-deploy@v5 根本不存在。而且不同 Action 的 input 命名也不一样(REMOTE_HOST vs remoteHost)。

解决:放弃第三方 Action,直接用原生 scpssh 命令,简单可靠。

坑 3:Secrets 传参问题

env 块传 secret 到 shell 变量,结果 scp $HOST 时变量是空的。

解决:直接在命令里用 ${{ secrets.XXX }} 引用,不经过 env。


效果

现在更新博客的流程变成了:

1
2
3
4
5
6
7
cd ~/my-blog
hexo new "新文章标题"
# 编辑文章...
git add .
git commit -m "新文章"
git push
# 等一分钟,刷新博客 → 已更新

打开 GitHub Actions 页面能看到每次构建的完整日志,哪一步失败了点进去就能看到。


和之前的东西怎么配合

现在有三层自动化,层层递进:

层级 工具 触发方式
服务器监控 check.sh + Glances 随时手动 / cron 定时
数据安全 backup.sh cron 每天凌晨 3 点
代码部署 GitHub Actions git push 自动触发

这三层覆盖了一个运维最核心的日常:监控 → 备份 → 部署


学到的概念

概念 解释
CI 持续集成:代码 push 后自动构建验证
CD 持续部署:构建成功后自动部署到目标环境
GitHub Actions GitHub 提供的 CI/CD 服务,免费额度够个人用
Workflow 工作流,定义在 .github/workflows/*.yml
Job 一次工作流运行,包含多个 Step
Step 一个步骤,可以是 Action 或 shell 命令
Secret 加密变量,存密钥/密码,不会在日志里明文显示
Runner GitHub 提供的构建机器(ubuntu-latest)

运维自动化不是一步到位的。先手写脚本,再一键脚本,最后才是 CI/CD。每一步都是在解决前一步的痛点。


部署工作流源码


从一键脚本到全自动部署
https://bingsv.github.io/2026/07/02/从一键脚本到全自动部署/
作者
Bingsv
发布于
2026年7月2日
许可协议