在Linux系统中,如何将开发者编写的应用程序转化为可靠的生产环境服务?本文将深入解析如何将Go程序封装为Systemd服务单元,并通过RPM包实现标准化部署。这套方案被广泛应用于企业级软件部署,如Nginx、MySQL等服务的分发安装。

Systemd

Systemd是内核之上的第一个用户进程(PID=1),由内核直接启动。其他服务/应用由 Systemd 直接或间接启动。管理所有用户空间进程:• 服务生命周期• 依赖解析• 资源隔离。

创建一个systemd服务

Systemd服务单元(testrpm.service)是一个配置文件,它定义了如何管理系统服务,Systemd服务单元示例解析:

[Unit]
Description=testrpm Daemon
After=network.service sys-fs-resctrl.mount  # 确保在网络和resctrl文件系统就绪后启动

[Service]
ExecStart=/usr/local/bin/testrpm --log_level debug # 启动test程序并传入相应参数以启动该服务
ExecStopPost=-/usr/local/bin/reset_test.sh # 服务停止后执行清理脚本
MemoryLimit=1G # 限制服务最多使用1GB内存,通过内核 cgroups 实现,支持动态调整:systemctl set-property testrpm MemoryLimit=5G
Restart=on-failure # 服务异常退出时自动重启
User=daemon_user

[Install]
WantedBy=multi-user.target  # 定义服务在系统多用户模式下启用

服务部署与管理:

# 部署服务文件
sudo cp testrpm.service /usr/lib/systemd/system/
# 重新加载配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start testrpm
# 设置开机自启
sudo systemctl enable testrpm
# 查看服务状态
sudo systemctl status testrpm
# 查看服务日志,日志统一管理,集成 Journald 组件,二进制日志存储(/var/log/journal/),结构化查询
journalctl -u testrpm -f

RPM包是干什么的

RPM包是部署工具和服务配置的载体,是Linux下主流的软件分发格式(将软件及其依赖打包成单个.rpm 文件),MySQL、Nginx 等软件都提供 RPM 包。自动解决软件依赖关系;支持升级、降级和回滚;统一安装、查询、卸载接口。

RPM文件是Red Hat系, 包管理工具是yum(旧)、dnf(新),默认系统CentOS/RHEL/Fedora/Alibaba Linux.

管理RPM/DEB包的平台:

开发者 ────┬───> 官方仓库(如Ubuntu Archive、RHEL BaseOS)
           │
           ├──> 第三方仓库(如EPEL、PPA)
           │
           └──> 私有仓库(如Nexus、Artifactory)
                  │
                  ▼
              客户端(yum/apt)───> 解析依赖并安装

创建一个RPM包

准备源码结构

testrpm-1.0.0/
├── cmd/
│   └── testrpm/          # Go主程序代码
├── config/
│   └── testrpm/
│       ├── testrpm.service  # Systemd服务文件
│       └── reset_testrpm.sh # 清理脚本
├── vendor/           # Go依赖
└── go.mod            # Go模块文件

编写SPEC文件,指导rpm包的安装

Name: testrpm
Version: 1.0.0
Release: 1.myself
Summary: testrpm Daemon

%description
System service for test rpm.

%prep
%setup -q  # 解压源码

%build
# 静态编译Go程序
CGO_ENABLED=0 GOOS=linux go build -o bin/testrpm ./cmd/testrpm

%install
# 安装二进制文件
install -m 0755 bin/testrpm %{buildroot}/usr/local/bin/testrpm
# 安装Systemd服务文件
install -m 0644 config/testrpm.service %{buildroot}/usr/lib/systemd/system/testrpm.service

%files
# 声明包含的文件
/usr/local/bin/testrpm
/usr/lib/systemd/system/testrpm.service

构建RPM包

# 生成源码压缩包
tar -czvf testrpm-1.0.0.tar.gz testrpm-1.0.0/
# 构建RPM
rpmbuild -bb testrpm.spec

RPM包安装行为:

  1. 二进制文件直接解压到目标路径(如/usr/local/bin/testrpm)
  2. Systemd服务文件部署到/usr/lib/systemd/system/
  3. 不会重新编译(二进制已在构建阶段生成)

技术方案对比

内核模块 vs RPM包 vs Systemd服务,某个需求我要选哪种方式实现?

  • Systemd服务:进程管理,长期稳定的服务,比如:apt install nginx + systemctl enable nginx
  • 内核模块: 内核级功能扩展,比如设备驱动、文件系统等内核级功能。
  • rpm包: 用户态应用程序分发。

比如:内核模块 nvidia.ko 提供 GPU 驱动能力。Systemd 服务 nvidia-persistenced 管理用户态守护进程。通过 udev 规则在设备插入时自动加载模块并启动服务。


文章作者: 易百分
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 易百分 !
  目录