☕ Java 服务开机自启 · 基于 shell 脚本 + systemd
记录于 2026-08-10 · 适用于任何通过 sh 脚本管理(start/stop/restart)的 Java 应用
📌 场景与目标
很多 Java 服务通过一个自定义脚本(如 shellTool.sh)来控制启动、停止和重启。我们希望该服务能在服务器重启后自动启动,并且能够使用 systemctl 统一管理,同时支持失败自动重启。
本文提供完整的 systemd 服务文件编写方法,并指导如何改造原脚本以生成 PID 文件,让 systemd 精准跟踪进程。
✅ 方案:使用 systemd(标准做法)
1. 确保脚本可执行并支持参数
假设脚本路径为 /home/job-plus/service/shellTool.sh,用法:
sh shellTool.sh [start|stop|restart|status]
先手动测试脚本是否能正常启动服务:
cd /home/job-plus/service
./shellTool.sh start
./shellTool.sh status
确保无报错后继续。
2. 改造脚本 —— 增加 PID 文件写入(关键)
⚠️ 为什么需要 PID 文件? systemd 的
Type=forking 模式需要知道主进程(Java 进程)的 PID,以便监控和管理。如果脚本用 nohup ... & 启动,需要将后台进程的 PID 写入文件。在 shellTool.sh 的 start 逻辑中,添加类似以下内容:
#!/bin/bash
# 假设你的启动命令为:
nohup java -jar my-app.jar --server.port=8080 > /dev/null 2>&1 &
# 获取后台进程 PID 并写入文件
echo $! > /home/job-plus/service/app.pid
如果脚本原本就有 PID 文件路径,请确保路径与后续 systemd 配置中的 PIDFile 一致。
3. 创建 systemd 服务文件
sudo vim /etc/systemd/system/personal_project_service.service
粘贴以下配置(务必修改所有路径):
[Unit]
Description=My Java Application Service
After=network.target
[Service]
# 工作目录(脚本和 jar 包所在目录)
WorkingDirectory=/home/job-plus/service
# 环境变量(如需要 JAVA_HOME)
Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk"
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# 启动命令
ExecStart=/bin/sh /home/job-plus/service/shellTool.sh start
# 停止命令
ExecStop=/bin/sh /home/job-plus/service/shellTool.sh stop
# 重启命令(可选)
ExecReload=/bin/sh /home/job-plus/service/shellTool.sh restart
# 进程管理类型:forking 表示后台 fork 子进程
Type=forking
# PID 文件路径,与脚本写入的一致
PIDFile=/home/job-plus/service/app.pid
# 自动重启策略
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
💡 如果不确定 Type 该用哪个: 如果你的脚本是前台运行(如
java -jar 不带 &),则用 Type=simple,并删除 PIDFile;但多数生产环境会用 nohup &,所以 forking 更常见。4. 启用服务并测试
sudo systemctl daemon-reload # 重新加载 systemd
sudo systemctl enable personal_project_service # 设置开机自启
sudo systemctl start personal_project_service # 立即启动
sudo systemctl status personal_project_service # 查看状态
如果状态显示 active (running),则配置成功。
5. 日常管理命令
- 启动:
sudo systemctl start personal_project_service - 停止:
sudo systemctl stop personal_project_service - 重启:
sudo systemctl restart personal_project_service - 查看实时日志:
sudo journalctl -u personal_project_service -f
🔄 备选方案:使用 /etc/rc.local(简单但不推荐)
对于老旧系统或不支持 systemd 的环境,可以将启动命令追加到 /etc/rc.local(确保文件有执行权限):
#!/bin/sh
# 在 exit 0 之前添加
/bin/sh /home/job-plus/service/shellTool.sh start
缺点:无进程监控,无自动重启,无法用 systemctl 管理。
⚠️ 常见问题 & 排错
- 服务启动失败,status 显示 failed:运行
sudo journalctl -u personal_project_service -n 30 --no-pager查看详细错误。 - PID 文件未生成:检查脚本中
echo $! > app.pid是否执行,且目录是否有写权限。 - 找不到 Java 命令:在
.service中通过Environment设置JAVA_HOME,或在脚本中使用绝对路径。 - 工作目录不正确:如果脚本或 jar 包依赖相对路径(如
./lib),务必设置WorkingDirectory。 - Type=forking 但脚本未 daemonize:如果脚本是直接前台启动,改用
Type=simple并删除PIDFile。
📝 总结
通过将自定义 shell 脚本包装为 systemd 服务,我们不仅实现了开机自启,还获得了进程守护、统一日志、依赖管理等一系列好处。这是目前 Linux 上管理 Java 服务的最佳实践。
如果遇到问题,请先手动执行脚本确保其本身没问题,再检查 systemd 配置细节——多数错误都源于路径、权限或 Type 选择不当。
浙公网安备 33010602011771号