Systemd 服务管理实战:从 Unit 编写到日常运维
Systemd 服务管理实战:从 Unit 编写到日常运维
把一套应用从”手动 nohup 启动”改成 systemd 托管,是运维规范化里回报最高的一件事——开机自启、崩溃拉起、日志集中、权限隔离一次全解决。这篇把从零手写 .service 到日常运维的完整过程捋一遍。
一、先理解三个角色
.service文件 = 一份”岗位说明书”:写明怎么启动、怎么停止、什么情况下重启;systemctl= 操作指令:对服务执行start / stop / enable / status;systemd= 管理进程:负责读懂说明书、监控所有服务。
现代主流 Linux 全部用 systemd,老掉牙的 SysV init 那套(/etc/inittab、rc.local 塞脚本)只在新装系统时偶尔遇见,不建议再往里写东西。
二、.service 文件的三段式
每个 Unit 文件由 [Unit]、[Service]、[Install] 三部分构成,缺一不可。放在 /etc/systemd/system/(管理员自定义,优先级最高)或 /usr/lib/systemd/system/(软件包自带)。
[Unit]:声明依赖
1 | [Unit] |
生产里最常见的坑:Java 应用在 MySQL 还没就绪时就启动了,连接池初始化报错。所以 After 一定要把依赖关系写清楚。
[Service]:定义怎么干活
1 | [Service] |
Type 的选择直接决定 systemd 能不能正确跟踪进程:
| Type | 适用场景 |
|---|---|
| simple | 前台运行的程序(Node.js、Python Web 服务) |
| forking | 会分叉后台的传统服务(Nginx、MySQL) |
| oneshot | 执行一次就退出的脚本,配合 RemainAfterExit=yes |
| notify | 支持 sd_notify 的现代程序,就绪后主动通知 |
[Install]:挂靠开机流程
1 | [Install] |
systemctl enable 的实质,就是在 /etc/systemd/system/multi-user.target.wants/ 下创建指向本文件的符号链接,开机进入多用户模式时自动拉起。
三、两个真实案例
案例 1:手工安装的 MySQL 5.7(Type=forking)
1 | [Unit] |
mysqld_safe 会分叉出真正的 mysqld 进程,所以必须 Type=forking 并指定 PIDFile,否则 systemd 会误判服务已退出。
案例 2:Java 微服务(Type=simple)
1 | [Unit] |
敏感配置(数据库密码)绝不写在 Unit 的 Environment 里明文,而是用 EnvironmentFile 指向权限 600 的配置文件,或交给密钥管理系统注入。
四、日常运维命令
1 | systemctl start/stop/restart/status 服务名 |
五、两个排障经验
- 改了单位文件不生效:九成是忘了
systemctl daemon-reload,新文件 systemd 根本不认识。 Restart=always的服务疯狂重启:启动即崩的程序会不停刷日志,光看status一时半会看不出来,要注意结合RestartSec和StartLimitIntervalSec/StartLimitBurst限制重启次数,同时去 journal 里看崩溃原因——这就是下一篇日志排查的内容。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 LuminDream's Blogs!


