大多数 Java 应用上线后,都是用 nohup + jar 的方式跑在后台,一旦服务器重启,进程就掉了,得手动再启。很原始,也不利于管理。
systemd 是主流 Linux 发行版默认的服务管理器,用它来管 Spring Boot 应用,可以做到开机自启、进程保活、日志收口、重启策略一条龙。
一、打包 Spring Boot 应用
Maven 打包:
./mvnw clean package -DskipTests
也可以直接用 Gradle:
./gradlew bootJar
打包完成后会生成一个 target/your-app.jar 文件。
二、编写 systemd Unit 文件
在 /etc/systemd/system/ 下创建一个 unit 文件,比如 myapp.service:
sudo vim /etc/systemd/system/myapp.service
内容如下:
[Unit]
Description=My Spring Boot Application
After=syslog.target network.target
[Service]
Type=simple
User=your_user
Group=your_group
ExecStart=/usr/bin/java -jar /path/to/your-app.jar
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=always
RestartSec=10
# 环境变量(可选)
Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="SPRING_PROFILES_ACTIVE=prod"
# 日志输出
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
关键参数说明:
| 参数 | 作用 |
|---|---|
Type=simple |
进程不退就算启动成功,适合 Spring Boot jar 模式 |
Restart=always |
进程异常退出后自动重启 |
RestartSec=10 |
重启前等待 10 秒 |
ExecStart |
启动命令,注意写绝对路径 |
ExecStop |
收到停止信号后优雅关机 |
Environment |
注入环境变量 |
三、注册并启动服务
# 重载 systemd(每次修改 unit 文件后都要执行)
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start myapp
# 查看状态
sudo systemctl status myapp
# 开机自启
sudo systemctl enable myapp
# 重启服务
sudo systemctl restart myapp
# 停止服务
sudo systemctl stop myapp
四、看日志
systemd 自己会收集 stdout/stderr,写到 journal 里:
# 实时跟踪日志
sudo journalctl -u myapp -f
# 查看最近 200 行
sudo journalctl -u myapp -n 200
# 按时间过滤
sudo journalctl -u myapp --since "1 hour ago"
# 清理旧日志(可选)
sudo journalctl --vacuum-time=7d
也可以让 journalctl 跟随服务进程 ID:
sudo journalctl -u myapp --identifier myapp
五、优雅关闭
Spring Boot 2.3+ 支持 /shutdown 端点,先要让应用收到 SIGTERM 后做善后:
在 application.yml 里配一下:
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
这样 systemctl stop 时,systemd 发 SIGTERM,Spring Boot 等完现有请求再退,不丢请求。
六、常见问题
1. 启动失败怎么办?
sudo systemctl status myapp
sudo journalctl -u myapp -xe
重点看 Executable not found 或 Java not found 这种报错。
2. 内存溢出了?
在 unit 文件的 ExecStart 里加 JVM 参数:
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /path/to/app.jar
3. 多实例部署
每个实例单独写一个 unit 文件,名字和服务名要不同,比如 myapp-prod.service 和 myapp-dev.service。
总结
用 systemd 管 Spring Boot 之后,服务稳定性提升一个档次,服务器重启不用手动跑,开源项目也原生好感。配合 journalctl 看日志,比翻 nohup.out 舒服多了。
文章评论