在麒麟V10服务器上,如果想配置程序开机启动主要有2种方法,第一种是使用systemd 服务,第二种是通过 crontab 的 @reboot 调用 Shell 脚本启动程序,本次介绍的是第二种方案。这种方式相对于第一种来说要更简单一些
我们只要使用crontab -e添加一个定时任务就行,比如要设置redis开机启动,则使用如下定时任务
@reboot /usr/local/bin/redis-server /data/redis/redis_server/redis.conf
但是你有时候会发现配置了开机启动的定时任务,但是程序没有启动基本上都是因为环境隔离与路径/权限问题导致的,虽然 @reboot 任务被 cron 正确执行了(所以你能在日志中看到“任务触发”),但 Shell 脚本在 cron 的受限环境中运行失败了,导致 程序未能真正启动,下面我们以开机启动springboot程序为例进行分析。
🔍 根本原因分析
cron 服务在执行任务时,使用的是一个极简的、与用户登录会话完全不同的环境。这个环境缺少:
- PATH环境变量不完整:
- cron 的默认 PATH 通常是 /usr/bin:/bin,可能不包含 java 命令的路径(如 /usr/local/java/bin)。
- 即使你在 .bashrc 或 .profile 中设置了 PATH,cron 不会加载这些文件。
- 缺少JAVA_HOME 等关键环境变量:
- Spring Boot 应用或 JVM 可能依赖 JAVA_HOME,比如:nacos的启动。
- 工作目录(Working Directory)不确定:
- @reboot 任务的工作目录可能是 /root 或 /,而你的脚本依赖相对路径(如 ./config/application.yml)。
- Shell 环境差异:
- cron 默认使用 /bin/sh,而不是你常用的 /bin/bash,某些 Bash 特性可能不支持。
- 权限或文件路径问题:
- 脚本、JAR 文件、日志目录的权限不足。
- 路径中包含空格或特殊字符未正确转义。
- 后台进程未正确守护:
- 如果没有正确使用 nohup 或 &,进程可能在 shell 退出时被终止。
✅ 解决方案
✅ 方案一:修改启动shell脚本,在 Shell 脚本中显式设置环境
修改你的启动脚本(例如 /data/myapp/start.sh),确保它不依赖外部环境。
#!/bin/bash
# /data/myapp/start.sh
# === 显式设置环境变量 ===
export JAVA_HOME=/usr/local/java-1.8.0-openjdk # 必须设置!用实际路径替换
export PATH=$JAVA_HOME/bin:$PATH # 确保 java 命令可用
export APP_HOME=/data/myapp # 应用根目录
# === 切换到应用目录 ===
cd "$APP_HOME" || {
echo "错误:无法进入目录 $APP_HOME" >&2
exit 1
}
# === 定义变量 ===
JAR_NAME="myapp.jar"
LOG_FILE="$APP_HOME/app.log"
PID_FILE="$APP_HOME/app.pid"
# === 检查是否已运行 ===
if [ -f "$PID_FILE" ]; then
if kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "程序已在运行,PID: $(cat $PID_FILE)"
exit 0
else
echo "发现旧的PID文件,但进程不存在,已清理。"
rm -f "$PID_FILE"
fi
fi
# === 启动 Spring Boot 应用 ===
# 使用 nohup 和 & 确保进程在后台持续运行
nohup java -jar "$JAR_NAME" \
--spring.profiles.active=prod \ # 可选:指定配置文件
>> "$LOG_FILE" 2>&1 &
# === 保存 PID ===
echo $! > "$PID_FILE"
echo "Spring Boot 应用已启动,PID: $!"
exit 0
✅ 方案二:在 crontab 中调用脚本时指定环境
编辑 crontab:
crontab -e
确保 crontab 头部设置环境:
# 设置 cron 环境
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
JAVA_HOME=/usr/local/java-1.8.0-openjdk
HOME=/root
# @reboot 启动应用,如果要排查无法启动,后面的输出日志路径一定要加上
@reboot /data/myapp/start.sh >> /data/myapp/myapp.log 2>&1
# 开机启动xxl-job
@reboot cd /data/xxl-job && /usr/local/java/bin/java -jar xxl-job-admin-2.4.1.jar >>/data/xxl-job/xxl-job.log 2>&1
🛠 排查步骤(关键!)
- 检查 crontab 日志:
# 查看 cron 是否执行了 @reboot
sudo grep CRON /var/log/cron
sudo grep cron /var/log/messages
# 输出示例:May 20 10:00:01 server CRON[1234]: (root) CMD (/opt/myapp/start.sh)
- 检查你的脚本日志:
确保脚本中有 >>/data/myapp/myapp.log 2>&1,然后查看日志:
tail -f /data/myapp/myapp.log
你很可能会看到 java: command not found 或 No such file or directory 错误。
- 手动模拟cron 环境测试:
# 模拟 cron 的极简环境
env -i \
SHELL=/bin/bash \
PATH=/usr/bin:/bin \
HOME=/root \
/bin/bash --norc --noprofile
# 在这个 shell 中执行你的启动脚本
/data/myapp/start.sh
如果失败,说明脚本依赖了外部环境。
- 确认 Java 路径:
# 在普通用户下
which java
# 输出可能是 /usr/local/jdk/bin/java
# 这个路径必须在脚本或 cron 的 PATH 中