使用 Systemd 和 Endless 专业部署 Go Web 应用实战教程
目标:将您的 Go 博客应用部署到生产服务器,并配置 systemd
和 endless
,以实现服务的稳定运行、开机自启、崩溃自愈,以及最重要的——不中断服务的平滑更新(无缝重启)。
技术栈:
- 应用框架: Go + Gin
- 无缝重启库:
endless
- 进程管理器:
systemd
(现代 Linux 发行版标配) - 部署路径:
/home/yys/blog
- 运行用户:
yys
第一部分:服务器环境准备
在开始部署之前,请确保您的服务器满足以下条件。
1. 安装 Go 环境
如果您的服务器上还没有安装 Go,请先安装。推荐安装最新稳定版。
2. 安装 Git (用于拉取代码)
3. 准备项目目录
创建您的项目将要存放的目录。
# 创建目录,-p 确保父目录不存在时也会被创建
mkdir -p /home/yys/blog
第二部分:部署与首次启动
现在,我们将把您的代码部署到服务器并进行首次编译和启动。
1. 获取源代码
登录到服务器,进入项目目录,然后使用 git
克隆您的项目。
cd /home/yys/blog
# 将 your_repo_url 替换成您真实的 Git 仓库地址
git clone your_repo_url .
注意:命令最后的 .
表示克隆到当前目录。
2. 安装 Go 依赖
进入项目目录后,endless
库也需要被下载。
# Go Modules 会自动处理 go.mod 文件中定义的依赖
go mod tidy
或者,如果您之前没有 go get
过,可以执行:
go get github.com/fvbock/endless
3. 编译您的应用
我们将源代码编译成一个单一的可执行二进制文件。
# -o blog_server 指定输出文件名为 blog_server
go build -o blog_server .
编译成功后,在 /home/yys/blog
目录下会有一个名为 blog_server
的文件。
授予执行权限 (重要):
chmod +x blog_server
4. 创建 Systemd Service 文件
这是整个部署流程的核心。
-
使用
nano
或vim
创建 service 文件:sudo nano /etc/systemd/system/blog.service
-
粘贴以下经过优化的配置内容:
这份配置包含了我们讨论过的所有最佳实践,如用户、路径、重启策略等。[Unit] Description=My Go Blog Application Service After=network.target mysql.service [Service] Type=simple User=root Group=root WorkingDirectory=/home/yys/blog ExecStart=/home/yys/blog/blog_server ExecReload=/bin/kill -HUP $MAINPID # --- 关键修改:增强重启策略 --- Restart=always # 将 on-failure 改为 always。 # 这会告诉 systemd:除了我手动执行 stop 命令,其他任何情况下的进程退出,都请你给我重启它。 # 这就完美覆盖了 reload 后新进程启动失败而退出的场景。 RestartSec=5s # 重启间隔保持不变,5秒是一个很合理的值。 StandardOutput=journal StandardError=journal LimitNOFILE=65536 [Install] WantedBy=multi-user.target
-
保存并退出编辑器。
5. 启动并管理您的服务
- 重载
systemd
配置使其识别您的新服务文件:sudo systemctl daemon-reload
- 设置开机自启:
sudo systemctl enable blog.service
- 立即启动服务:
sudo systemctl start blog.service
- 检查服务状态:
sudo systemctl status blog.service
Active: active (running)
。如果有错误,日志中会有提示。
至此,您的博客已经作为后台服务在稳定运行了!
第三部分:不中断服务的平滑更新 (核心操作)
当您未来更新了网站代码后,您不再需要停止服务。只需遵循以下简单的“三步曲”。
步骤 1: 在服务器上更新代码
登录服务器,进入项目目录,拉取最新的代码。
cd /home/yys/blog
git pull
步骤 2: 重新编译
用新代码生成新的 blog_server
二进制文件,它会覆盖掉旧版本。
go build -o blog_server .
步骤 3: 执行无缝重启
这是最神奇的一步。执行 reload
命令,systemd
会向旧进程发送 HUP
信号,endless
会处理剩下的一切,完成新旧版本的平滑交接。
sudo systemctl reload blog.service
您的网站更新就完成了,整个过程对用户零中断!
第四部分:日常维护
查看日志
当您需要排查问题时,journalctl
是您的好朋友。
- 查看服务的实时日志 (类似
tail -f
):sudo journalctl -u blog.service -f
- 查看最近的 100 条日志:
sudo journalctl -u blog.service -n 100 --no-pager
其他常用命令
- 停止服务:
sudo systemctl stop blog.service
- 硬重启服务 (会中断):
sudo systemctl restart blog.service
第五部分:手动更新与部署流程 (通过 Git 同步)
目标:在您本地完成代码修改并推送到 Git 仓库后,通过一系列标准的手动命令,在服务器上安全、无缝地完成应用的更新和部署。
工作流程:
- 本地: 开发者
add
->commit
->push
代码。 - 服务器: 管理员登录后,依次执行
git pull
->go build
->systemctl reload
。
场景:您在本地电脑上完成了新的功能开发或 bug 修复
步骤 1: 在本地提交并推送代码
在您的本地开发环境(例如您的 WSL 或 Windows 电脑)的项目根目录下,执行标准的 Git 操作,将您的更改推送到远程仓库(如 GitLab/GitHub)。
- 查看更改状态:
git status
- 添加所有更改到暂存区:
git add .
- 提交更改并附上有意义的说明:
git commit -m "feat: 增加文章详情页的xxx功能"
- 推送到远程主分支:
git push origin main
完成这一步后,您的最新代码就已经安全地保存在远程 Git 仓库中了。
步骤 2: 在服务器上拉取最新代码
现在,切换到您的服务器终端,准备更新正在运行的应用。
-
通过 SSH 登录到您的服务器。
-
进入您的项目部署目录:
cd /home/yys/blog
-
使用
git pull
拉取最新代码:
这条命令会从远程仓库获取您刚刚推送的最新代码,并与服务器上的本地代码进行合并。git pull
您应该能看到类似
Updating ...
的输出,表明代码已更新。
步骤 3: 在服务器上重新编译应用
现在源代码已经更新,我们需要用它来生成一个新的、包含了新功能的可执行文件。
-
确保您仍在项目根目录 (
/home/yys/blog
)。 -
执行编译命令:
这会生成一个名为blog_server
的新二进制文件,并覆盖掉旧的那个。go build -o blog_server .
-
(可选但推荐) 检查文件是否更新:
用ls -l
命令查看blog_server
的修改时间,确保它就是您刚刚编译的时间。ls -l blog_server
步骤 4: 在服务器上执行无缝重启
新的二进制文件已经准备就绪,现在是时候让正在运行的服务加载它了。
-
执行
systemctl reload
命令:
这个命令会向正在运行的旧进程发送HUP
信号,触发endless
库的无缝重启机制。sudo systemctl reload blog.service
-
验证更新是否成功:
reload
命令会立即返回,但后台的新旧进程交接需要几秒钟。您可以等待 2-3 秒后,通过以下命令来确认服务状态:sudo systemctl status blog.service
- 观察
Active
状态: 应该显示active (running)
。 - 观察
Main PID
: 您会发现 PID 已经变成了一个新的数字,这证明新进程已经成功启动并接管了服务。
- 观察
-
最终测试:
打开浏览器,访问您的博客网站。刷新页面,您应该就能看到您之前修改的新功能或修复的内容了。
这个“拉取 -> 编译 -> 重载”的三步曲是手动部署中非常标准和专业的实践。
本文作者: 永生
本文链接: https://www.yys.zone/detail/?id=437
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
评论列表 (0 条评论)