11 · systemd 服务管理
一句话定位:把你的 Java 应用做成系统服务——崩了自动拉起、随机器开机自启、日志统一管理。比 nohup 更专业。
1. 为什么用 systemd 而不是 nohup
| nohup | systemd | |
|---|---|---|
| 开机自启 | ❌ 要自己写 | ✅ 一条命令 |
| 崩溃自动重启 | ❌ | ✅ |
| 统一管理 | ❌ 到处找PID | ✅systemctl统管 |
| 日志 | 自己重定向 | ✅journalctl统一 |
systemd 是现代 Linux(CentOS7+/Ubuntu16+)的标准服务管理器,几乎所有服务(nginx/mysql/docker)都归它管。
2. systemctl 操作已有服务
systemctl start nginx# 启动systemctl stop nginx# 停止systemctl restart nginx# 重启systemctl reload nginx# 重载配置(不中断)systemctl status nginx# ★查看状态(最常用,看运行情况+最近日志)systemctlenablenginx# 设为开机自启systemctl disable nginx# 取消开机自启systemctl is-enabled nginx# 查是否自启systemctl is-active nginx# 查是否在运行systemctl list-units--type=service# 列出所有服务没权限前面加
sudo。
3. 把自己的 Java 应用做成 systemd 服务
创建服务定义文件/etc/systemd/system/myapp.service:
[Unit] Description=My Spring Boot App After=network.target # 网络就绪后再启动 [Service] Type=simple User=deploy # 用哪个用户跑(别用root) WorkingDirectory=/opt/app # 工作目录 # 启动命令(注意用绝对路径) ExecStart=/opt/jdk-17/bin/java -Xms2g -Xmx2g -Dspring.profiles.active=prod -jar /opt/app/app.jar # 停止用 SIGTERM(优雅停机) ExecStop=/bin/kill -15 $MAINPID SuccessExitStatus=143 # 143 = 被SIGTERM正常终止,算成功 Restart=always # ★崩溃自动重启 RestartSec=5 # 重启间隔5秒 # 环境变量(可选) Environment="JAVA_HOME=/opt/jdk-17" # 日志(交给 journald,或自己重定向) StandardOutput=append:/opt/app/logs/app.log StandardError=append:/opt/app/logs/app.log [Install] WantedBy=multi-user.target # 开机自启的目标4. 启用你的服务
# 1. 改了 .service 文件后,重载 systemd 配置systemctl daemon-reload# 2. 启动systemctl start myapp# 3. 查看状态(确认 active running)systemctl status myapp# 4. 设为开机自启systemctlenablemyapp# 之后日常操作就和操作 nginx 一样systemctl restart myapp systemctl stop myapp5. 查服务日志:journalctl
journalctl-umyapp# 看 myapp 服务的全部日志journalctl-umyapp-f# ★实时追踪(类似 tail -f)journalctl-umyapp-n200# 最近200行journalctl-umyapp--since"10:00"# 从10点开始journalctl-umyapp--sincetoday# 今天的journalctl-umyapp-perr# 只看 error 级别journalctl-umyapp--since"2026-10-14 10:00"--until"10:30"# 时间段如果
.service里已经把日志重定向到文件(StandardOutput=append:...),也可以直接tail -f /opt/app/logs/app.log。
6. 实战:完整部署一个服务
# 1. 上传 jar(本地)scpapp.jar prod:/opt/app/# 2. 写 service 文件(服务器)sudovim/etc/systemd/system/myapp.service# 粘贴上面的模板# 3. 启用sudosystemctl daemon-reloadsudosystemctlenablemyappsudosystemctl start myapp# 4. 验证systemctl status myapp journalctl-umyapp-f# 5. 以后升级scpapp.jar prod:/opt/app/# 传新包sudosystemctl restart myapp# 一条命令重启7. 坑与最佳实践
- ✅ 改完
.service文件必须systemctl daemon-reload,否则不生效。 - ✅
ExecStart里的java、jar都要写绝对路径(systemd 环境没有你的 PATH)。 - ✅
Restart=always让服务崩溃自愈,生产必备。 - ✅
ExecStop用kill -15(优雅),配SuccessExitStatus=143避免被误判为失败。 - ⚠️ 用非 root 用户(
User=deploy)跑,注意目录和日志文件该用户要有权限。 - ⚠️ 启动失败看
systemctl status myapp和journalctl -u myapp -n 50,错误都在里面。 - 💡 想禁止自动重启排查问题,临时
systemctl stop myapp,别一直被拉起干扰。
8. 本篇速记
systemctl start/stop/restart/status 服务# 控制服务systemctl enable/disable 服务# 开机自启systemctl daemon-reload# 改配置后重载 ★journalctl-u服务-f# 实时日志journalctl-u服务-n200# 最近200行# 服务定义:/etc/systemd/system/xxx.service