CentOS7 systemd注册Java jar为系统服务

把SpringBoot、Quartz、Netty、普通可执行jar丢进Linux,开机自启、挂掉自启、统一日志、一行命令启停,全靠systemd。下面这份踩坑总结,照着敲,五分钟完事。

一、先想清楚:jar到底需要啥
JDK路径、运行用户、内存参数、外置配置、日志目录、端口冲突,这六件事没理顺,服务文件写得再漂亮也起不来。用which java确认JDK,用mkdir -p /opt/myapp/{lib,logs,config}把目录建好,再给非root用户赋权:chown -R app:app /opt/myapp。
二、手写一个最小可运行的service文件
路径固定:/etc/systemd/system/demo.service,文件名即服务名,改完记得systemctl daemon-reload。
[Unit]
Description=Demo Java App
After=network.target
[Service]
Type=simple
User=app
Group=app
WorkingDirectory=/opt/myapp
ExecStart=/usr/lib/jvm/java-17-openjdk/bin/java \
-Xms512m -Xmx1g \
-Dspring.config.location=/opt/myapp/config/ \
-Dlogback.configurationFile=/opt/myapp/config/logback.xml \
-jar /opt/myapp/lib/demo.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
StandardOutput=append:/opt/myapp/logs/stdout.log
StandardError=append:/opt/myapp/logs/stderr.log
[Install]
WantedBy=multi-user.target
关键点解释
Type=simple:jar里没写Systemd notify就用simple,别选notify。SuccessExitStatus=143:Java收到SIGTERM会返回143,告诉systemd这是正常退出,别重启。Restart=on-failure:只认异常退出码,自己System.exit(0)不会触发重启。StandardOutput=append::把控制台日志直接重定向到文件,journalctl -u demo依旧能看,双重保险。
三、一次启停全流程
systemctl daemon-reload
systemctl enable demo # 开机自启
systemctl start demo
systemctl status demo # 看Active、看内存、看最后一次日志
systemctl stop demo
systemctl restart demo
四、日志怎么查才快
实时刷:journalctl -u demo -f
翻昨天:journalctl -u demo --since "2025-09-16 00:00:00" --until "2025-09-16 23:59:59"
只想异常:journalctl -u demo -p err
文件太大给logrotate:在/etc/logrotate.d/demo里写四行,按日切割、保留30份、压缩、不丢日志。
五、常见翻车现场
1. 启动5秒就挂
journalctl里提示Permission denied,90%是User=app没权限写日志目录,chown搞定。
2. 端口被占用
netstat -tunlp | grep 8080看是谁,改配置或systemctl stop另一个服务。
3. 中文乱码
service文件里加Environment="LANG=zh_CN.UTF-8",jar启动参数再加-Dfile.encoding=UTF-8。
4. 重启整个服务器后没自启
systemctl is-enabled demo返回disabled,说明enable那步没敲,重新跑一遍。
六、想一次部署多台机器
把jar、config、service文件打成一个tar包,Ansible复制+systemd模块批量下发,两分钟全搞定。变量写在inventory里,端口、内存、环境区分清楚,谁出问题一眼定位。
七、升级jar零 downtime
service文件里把ExecStart指向软链/opt/myapp/lib/demo-current.jar,发版时上传新包,切链:ln -sf demo-20250917.jar demo-current.jar,再systemctl restart demo,回滚只需把链指回去。对外提供socket的服务,可再加ExecReload=/bin/kill -HUP $MAINPID实现平滑热加载,无需重启。
八、被问最多的八个命令汇总
1. systemctl list-units --type=service --state=failed // 看系统里谁挂了
2. systemctl cat demo // 立即查看最终生效的service全文
3. systemctl show demo --property=MainPID // 拿PID,对接监控
4. systemd-analyze blame // 开机谁最慢
5. systemctl mask tmp.mount // 不让某个自带服务启动,省内存
6. systemctl edit demo // 新建drop-in片段,升级不覆盖
7. journalctl -b // 本次启动以来的所有日志
8. systemctl get-default // 看默认启动目标,图形还是多用户
CentOS7下,写好service文件、给足权限、配好日志、加Restart,Java jar就能像原生服务一样稳;会查journalctl,会daemon-reload,就能在十分钟内让任何jar具备生产级可用性。

