博客运维:通过 Git 更新服务器代码与数据库的完整流程
本地开发 → Git 推送 → 服务器拉取 → 构建重启。本文记录从本地博客修改到服务器生效的完整运维流程,包括代码更新、数据库同步、常见错误处理。
博客运维:通过 Git 更新服务器代码与数据库的完整流程
前言
博客基于 Next.js + Prisma + SQLite 搭建,部署在腾讯云 Ubuntu 22.04 上,通过 Nginx 反向代理 + PM2 进程管理提供服务。日常更新内容包括:
- 代码修改(新功能、Bug 修复、样式调整)
- 内容修改(新增/编辑文章、修改分类)
- 数据库同步(本地新增文章后同步到服务器)
本文记录完整的更新流程和踩坑记录。
一、基础环境确认
服务器目录结构:
/home/ubuntu/JoeBlog # 项目根目录
├── prisma/
│ └── dev.db # SQLite 数据库文件(默认路径)
├── .next/ # Next.js 构建产物
├── .env.production # 生产环境变量
└── package.json
关键环境变量文件 .env.production:
DATABASE_URL="file:./prisma/dev.db"
二、代码更新流程
本地开发
# 修改代码...
cd /f/GitHub_project/BLOG/Joe_blog
# 测试
npm run dev
# 提交
git add .
git commit -m "feat: 添加了新功能"
本地 Git 代理注意
如果本地有 Git 代理设置,提交前需检查:
git config --global http.proxy
git config --global https.proxy
有代理的话推送可能会走代理导致失败,可以临时绕过:
git -c http.proxy= -c https.proxy= push
推送到 GitHub
git push
# 或者 bypass 代理
git -c http.proxy= -c https.proxy= push
服务器拉取
登录服务器:
ssh ubuntu@你的服务器IP
cd /home/ubuntu/JoeBlog
拉取最新代码:
# 先备份当前代码(可选)
# cp -r . ~/joeblog-backup-$(date +%Y%m%d)
git pull
如果服务器上 Git 配置了 SSH key 但推送方式变了,可能需要先切分支或处理冲突:
# 如果有冲突
git stash # 暂存本地修改
git pull # 拉取远程
git stash pop # 恢复本地修改(手动解决冲突)
安装依赖
npm install
注意:如果 package.json 或 package-lock.json 没有变化,可以跳过这步。
构建
npm run build
Next.js 构建过程会:
- Prisma generate(如果 schema 变化)
- 编译 TypeScript 和 JSX
- 生成静态页面(ISR/SSG)
- 输出到
.next/目录
重启服务
pm2 restart joe-blog
如果 PM2 中没保存进程名,先查看:
pm2 list
确认服务正常:
curl -o /dev/null -s -w "%{http_code}" http://localhost:3000
# 返回 200 表示正常
ss -tlnp | grep 3000
# 确认 PM2 进程在监听
三、数据库同步流程
场景 1:只在本地新增了文章,数据库文件整体同步
最简单的方式:直接把本地数据库文件 scp 到服务器覆盖。
# 本地执行(在 Windows 上)
scp /f/GitHub_project/BLOG/Joe_blog/prisma/dev.db ubuntu@服务器IP:/home/ubuntu/JoeBlog/prisma/
重要:scp 前先停掉 PM2 服务,避免文件正在被写入导致损坏:
# 服务器上
pm2 stop joe-blog
# 本地 scp 上传
scp /f/GitHub_project/BLOG/Joe_blog/prisma/dev.db ubuntu@服务器IP:/home/ubuntu/JoeBlog/prisma/
# 重启
pm2 restart joe-blog
场景 2:只想同步部分数据(新增的文章)
最佳实践是只导出新增的文章 SQL 并执行。但 SQLite 是文件型数据库,对于小博客项目,直接用文件覆盖是最简单可靠的方案。
场景 3:修改了 Prisma Schema
如果改了 schema.prisma(新增字段、修改模型等),除了拉取代码外还需要:
cd /home/ubuntu/JoeBlog
npx prisma generate # 重新生成 Prisma Client
npx prisma db push # 同步 schema 到数据库(不会删除数据)
prisma db push 会在不丢失现有数据的前提下修改表结构。如果需要重置数据可以 prisma db push --force-reset(会清空数据)。
上传数据库文件的最佳实践
# 完整流程(服务器上执行)
pm2 stop joe-blog
cp prisma/dev.db prisma/dev.db.bak # 先备份旧的
# 本地执行 scp
scp /f/GitHub_project/BLOG/Joe_blog/prisma/dev.db ubuntu@服务器IP:/home/ubuntu/JoeBlog/prisma/
# 重启
pm2 restart joe-blog
# 验证
curl http://localhost:3000
四、常见错误处理
1. PM2 端口冲突(EADDRINUSE)
# 现象:pm2 start 后进程显示 online 但网站无法访问
# 查看日志
pm2 logs
# 如果看到 EADDRINUSE
ss -tlnp | grep 3000 # 找到占用的 PID
kill <PID> # 杀死旧进程
pm2 delete joe-blog && pm2 start npm --name "joe-blog" -- start
pm2 save
2. Prisma 找不到数据库
# 现象:构建或运行时 Prisma 报错
# Error: Environment variable not found: DATABASE_URL
# 检查 .env.production 文件是否存在
cat /home/ubuntu/JoeBlog/.env.production
# 缺少则创建
echo 'DATABASE_URL="file:./prisma/dev.db"' > /home/ubuntu/JoeBlog/.env.production
3. PM2 Daemon 崩溃 / 进程列表丢失
# 现象:pm2 status 显示空列表,daemon 每次都重新 spawn
# 解决方案
cd /home/ubuntu/JoeBlog
pm2 start npm --name "joe-blog" -- start
pm2 save
# 检查 systemd 自启用户是否正确
cat /etc/systemd/system/pm2-ubuntu.service | grep User
# 如果 User 和实际运行用户不匹配,需要修改
4. Git 推送被代理拦截
# 现象:git push 报代理错误
# 跳过代理直接推送
git -c http.proxy= -c https.proxy= push
五、完整更新脚本示例
以下是服务器上执行的完整更新命令序列:
#!/bin/bash
# update-blog.sh - 服务器上执行
set -e
echo "=== Step 1: 拉取代码 ==="
cd /home/ubuntu/JoeBlog
git pull
echo "=== Step 2: 安装依赖 ==="
npm install
echo "=== Step 3: 构建 ==="
npm run build
echo "=== Step 4: 重启服务 ==="
pm2 restart joe-blog
echo "=== Step 5: 验证 ==="
sleep 3
STATUS=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:3000)
if [ "$STATUS" = "200" ]; then
echo "✅ 部署成功,HTTP $STATUS"
else
echo "❌ 部署异常,HTTP $STATUS"
fi
总结
整套运维流程并不复杂,核心就是:本地改 → git push → 服务器 git pull → npm install(如有新依赖)→ npm run build → pm2 restart。数据库同步更简单,SQLite 文件直接 scp 覆盖即可。
关键记住三点:
- scp 数据库前先停 PM2,避免文件损坏
- 每次更新后 pm2 restart,别忘记 pm2 save 持久化进程列表
- 端口排查用 ss 不用 lsof