当前位置:首页>Linux>Linux 实战:自定义 systemd 服务

Linux 实战:自定义 systemd 服务

  • 2026-09-10 18:49:18
Linux 实战:自定义 systemd 服务

在 Linux 系统中,通过 systemd 管理自定义程序(如 Python 脚本、Node.js 应用、Go 二进制程序等)非常常见。要实现这一点,你需要创建一个 .service 单元文件。

本文将详细讲解 .service 文件的结构、常用配置项、编写规范及完整示例。

一、.service 文件的位置

  • 系统级服务(推荐用于生产环境):/etc/systemd/system/your-service-name.service
  • 发行版默认服务:/usr/lib/systemd/system/(或 /lib/systemd/system/)
“

注意:

  • 系统级服务仅 root 可写,优先级高,不会被软件包更新覆盖。
  • 发行版默认服务通常由软件包管理器安装,不建议手动修改。
  • 自定义服务一律放在 /etc/systemd/system/

二、基本结构

.service 文件采用 INI 风格语法,分为若干节(section),最常用的有:

  • [Unit]:描述服务元信息和依赖关系
  • [Service]:定义如何启动、运行和停止服务
  • [Install]:定义启用(enable)时的行为

三、各节详解

[Unit] 节

指令
说明
Description=
服务的简短描述(必填,用于 systemctl status 显示)
Documentation=
文档链接(可选,如 man 手册、URL)
After=
在哪些单元启动之后启动本服务(如 network.target)
Before=
在哪些单元之前启动
Wants=
弱依赖(推荐)——若依赖项失败,本服务仍会启动
Requires=
强依赖——若依赖项失败,本服务不会启动
Conflicts=
冲突的服务(不能同时运行)

示例:

[Unit]
Description=My Custom Web Application
Documentation=https://example.com/docs
After=network.target
Wants=network.target

⚠️ 注意:After 不表示依赖!它只控制启动顺序。要建立依赖,请配合 Wants 或 Requires。

[Service] 节(核心)

这是最关键的部分,定义服务如何运行。

基础类型

  • Type=simple(默认):主进程立即启动,systemd 认为服务已就绪。
  • Type=forking:服务会 fork 子进程后退出父进程(传统守护进程)。
  • Type=oneshot:执行一次即退出(如初始化脚本),常配合 RemainAfterExit=yes。
  • Type=notify:服务通过 sd_notify() 通知 systemd 已就绪(需程序支持)。
  • Type=idle:延迟启动,直到其他任务完成(较少用)。

关键指令

指令
说明
ExecStart=
启动服务时执行的命令(必须)
ExecStartPre=
启动前执行的命令(可多个)
ExecStartPost=
启动后执行的命令
ExecStop=
停止服务时执行的命令(默认发送 SIGTERM)
ExecReload=
重载配置时执行的命令(对应 systemctl reload)
Restart=
何时自动重启(always, on-failure, on-abnormal, on-watchdog, on-success, no)
RestartSec=
重启前等待的秒数(如 5s)
User=
 / Group=
以指定用户/组身份运行(安全最佳实践!)
WorkingDirectory=
工作目录
Environment=
设置环境变量(如 Environment=NODE_ENV=production)
EnvironmentFile=
从文件加载环境变量(如 /etc/myapp.conf)
PIDFile=
指定 PID 文件路径(仅用于 Type=forking)
StandardOutput=
 / StandardError=
重定向标准输出/错误(如 journal, syslog, file:/var/log/app.log)
TimeoutStartSec=
启动超时时间(默认 90 秒)
KillMode=
终止方式(control-group 默认,杀掉整个 cgroup)

[Install] 节

控制 systemctl enable 的行为。

指令
说明
WantedBy=
启用服务时,将其链接到哪个 target(最常用)
RequiredBy=
强依赖目标(少用)
Alias=
服务别名

最常见写法:

[Install]
WantedBy=multi-user.target

这表示:当系统进入多用户模式(即正常运行状态)时,自动启动该服务。

四、案例

案例1:启动一个jar

创建一个服务单元文件,例如 demo.service:

[Unit]
Description=a demo project
After=network.target

[Service]
Type=simple
ExecStart= /usr/java/jdk/bin/java -jar /usr/project/demo.jar

[Install]
WantedBy=multi-user.target

相关命令

# 重载 systemd 配置
sudo systemctl daemon-reexec
sudo systemctl daemon-reload

#
 启动服务
sudo systemctl start demo

#
 设置开机自启
sudo systemctl enable demo

#
 查看状态
sudo systemctl status demo

#
 实时查看日志
sudo journalctl -u demo -f

#
 查看最近 100 行
sudo journalctl -u demo -n 100

五、常见问题

为什么用 systemd 管理 Java 应用?

很多 Java 后端服务(如 Spring Boot、Quarkus、Micronaut 等)最终会打包成一个可执行的 fat JAR 文件。虽然可以直接用 nohup java -jar app.jar & 启动,但这种方式存在明显缺陷:

  • 无法开机自启
  • 崩溃后不会自动重启
  • 日志分散,难以追踪
  • 无法通过统一命令管理(start/stop/status)

而通过 systemd 自定义服务,你可以获得:

  • ✅ 开机自启
  • ✅ 进程守护与自动重启
  • ✅ 标准化日志(journalctl)
  • ✅ 资源限制与安全隔离

最新文章

随机文章