systemctl 服务管理:注册自定义应用为系统服务

前言

在 Linux 服务器上,我们经常需要将自研的应用程序(如 Web API、WebSocket 服务、后台任务进程等)以守护进程的方式长期运行,并具备开机自启、崩溃自动恢复、日志统一管理等功能。

systemd 是当今绝大多数 Linux 发行版(CentOS 7+、Ubuntu 16.04+、Debian 8+ 等)默认的 init 系统,而 systemctl 是其管理服务的核心命令。

通过编写一个 .service 单元文件,就可以将任意可执行程序注册为系统服务,享受与 nginx、sshd 等系统服务同等级别的管理能力——包括 start/stop/restartenable/disable 自启、journalctl 日志查看、以及进程崩溃后自动重启。

本文以二进制可执行文件Jar 包两种常见场景为例,走通从编写 .service 文件到启停验证的完整流程。

添加服务

准备一个最小单元文件。

假设你的可执行文件放在 /data/wwwjarapi/8931mcws/xh-control-ws,示例中用 root 用户(生产环境建议创建专用系统用户运行)。

创建文件

1
vi /etc/systemd/system/xh-control-ws.service

启动GO服务示例

内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[Unit]
Description=xh-control-ws
After=network.target

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/data/wwwjarapi/8931mcws
ExecStart=/data/wwwjarapi/8931mcws/xh-control-ws
Restart=always
RestartSec=5s
StartLimitInterval=60s
StartLimitBurst=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

启动 Jar 包示例

如果你的应用是 Spring Boot / Quarkus 等 Jar 包,ExecStart 改为 java -jar,并建议指定 JVM 参数。

/etc/systemd/system/xhschool-suser.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Unit]
Description=my-api-service
After=network.target

[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/data/wwwjarapi/schoolcloudapi/8304suser
ExecStart=/usr/java/jdk1.8.0_221-amd64/bin/java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Xms256m -Xmx512m -jar suser-0.0.1-SNAPSHOT.jar
SuccessExitStatus=143
Restart=always
RestartSec=5s
StartLimitInterval=60s
StartLimitBurst=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

与二进制示例的区别说明:

SuccessExitStatus=143 是 Jar 服务特有的配置。Spring Boot 默认注册了 shutdown hook,收到 SIGTERM 后优雅关闭、进程退出码为 143,若不设置此项,systemctl stopstatus 可能会显示 Failed,容易误判。

配置说明

[Unit]Description 为服务描述,After=network.target 表示等网络就绪后再启动。

[Service] 配置说明:

Type=simple → 拉起进程就算启动完成

User=root → 用 root 身份跑(示例用,生产建议专用用户)

Group=root → 用户组 root

WorkingDirectory=… → 先 cd 到该目录再启动

ExecStart=… → 要执行的命令(必须绝对路径)

Restart=always → 一挂就重启

RestartSec=5s → 等待5秒再重启

StartLimitInterval=60s + StartLimitBurst=10 → 60 秒内超 10 次重启就放弃

StandardOutput=journal → 把 stdout 打进 systemd 日志

StandardError=journal → 把 stderr 也打进 systemd 日志

启用并立即启

1
2
sudo systemctl daemon-reload
sudo systemctl enable --now xh-control-ws

之后若修改过 .service 文件,需要先执行 daemon-reloadstartrestart

验证

手动 kill 进程:

1
2
ps -ef | grep xh-control-ws
sudo kill -9 <pid>

几秒后执行 systemctl status xh-control-ws,应看到 Active: active (running),说明已被自动拉起。

查看状态

1
systemctl status xh-control-ws

查看实时日志:

1
journalctl -u xh-control-ws -f

服务启动/停止

正常停止/启动

1
2
3
4
5
6
7
8
# 只停掉当前运行实例(下次开机若 enable 了仍会自启)
sudo systemctl stop xh-control-ws

# 需要时再启动
sudo systemctl start xh-control-ws

# 重启(先 stop 再 start)
sudo systemctl restart xh-control-ws

彻底禁用自启

1
2
# --now 顺便帮你 stop
sudo systemctl disable --now xh-control-ws