继续潜水

导航

 

☕ 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.shstart 逻辑中,添加类似以下内容:

#!/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 选择不当。

posted on 2026-08-10 10:48  继续潜水  阅读(5)  评论(0)    收藏  举报