#. ____ _ __ _ _
# /\/___"_ __ _ _(_)_ __ __ _
# ( ( )___ | "_ | "_| | "_ /_` |
# \/___)| |_)| | | | | || (_| | ) ) ) )
# "|____| .__|_| |_|_| |___, | ////
#=========|_|==============|___/=/_/_/_/
# : Spring Boot 启动脚本:
#
### 开始初始化信息
# Provides: {{initInfoProvides:spring-boot-application}}
# 必需的-Start: {{initInfoRequiredStart:$remote_fs $syslog $network}}
# 必需的Stop: {{initInfoRequiredStop:$remote_fs $syslog $network}}
# 默认启动: {{initInfoDefaultStart:2 3 4 5}}
# 默认Stop: {{initInfoDefaultStop:0 1 6}}
# Short-Description: {{initInfoShortDescription:Spring Boot 应用程序}}
# Description: {{initInfoDescription:Spring Boot 应用程序}}
# chkconfig: {{initInfoChkconfig:2345 99 01}}
###END 初始化信息
# [ -z STRING ] 如果“STRING”的长度为零则为真。
# [ -n STRING ] 如果“STRING”的长度非零则为真。
# 判断是否开启调试模式。如果打开调试模式,则通过set -x 来显示执行的命令。
[[ -n "$DEBUG" ]] 设置-x
# 初始化.conf文件无法提供的变量
# 获取工作空间路径
WORKING_DIR="$(pwd)"
# shellcheck 禁用=SC2153
# 获取jar文件路径并分配
[[ -n "$JARFILE" ]] jarfile="$JARFILE"
# 获取APP名称
[[ -n "$APP_NAME" ]] 身份="$APP_NAME"
# 按照符号链接找到真正的jar 并检测init.d 脚本
cd "$(目录名"$0")" || 1号出口
# 如果jarfile不存在,则将当前路径/当前执行文件名赋给jarfile
[[ -z "$jarfile" ]] jarfile=$(pwd)/$(基本名称"$0")
# 判断jarfile是否是符号链接。 -L 判断文件是否是符号链接
while [[ -L "$jarfile" ]];做
# 如果jarfile包含“init.d”,则将当前执行文件名赋给init_script
[[ "$jarfile"=~ init.d ]] init_script=$(basename "$jarfile")
# 获取符号链接指向的位置
jarfile=$(readlink "$jarfile")
# 输入文件的真实目录
cd "$(目录名"$jarfile")" || 1号出口
# 获取jar文件的绝对路径
jarfile=$(pwd)/$(基本名称"$jarfile")
完毕
# 进入jarfile文件所在目录,获取该文件的绝对目录值并将其分配给jarfolder。 pwd -P 显示当前目录的绝对路径
jarfolder="$( (cd "$(dirname "$jarfile")" pwd -P) )"
# 返回原来的工作空间
cd "$WORKING_DIR" || 1号出口
# 获取任何配置文件
# 获取配置文件名。从这里可以看出,配置文件名和可执行文件名除了后缀之外应该是一样的。
configfile="$(基本名称"${jarfile%.*}.conf")"
# 初始化CONF_FOLDER 位置,默认为jarfolder
# 如果CONF_FOLDER值为空,则通过jarfolder定义CONF_FOLDER的值
[[ -z "$CONF_FOLDER" ]] CONF_FOLDER="{{confFolder:${jarfolder}}}"
# shellcheck 源=/dev/null
# 如果配置文件存在,则source配置文件
[[ -r "${CONF_FOLDER}/${configfile}" ]] 源"${CONF_FOLDER}/${configfile}"
# 如果配置文件未提供,则初始化PID/LOG 位置
#如果配置文件中没有定义日志输出目录、pid文件目录等,则会初始化为默认值。
[[ -z "$PID_FOLDER" ]] PID_FOLDER="{{pidFolder:/var/run}}"
[[ -z "$LOG_FOLDER" ]] LOG_FOLDER="{{logFolder:/var/log}}"
! [[ "$PID_FOLDER"==/* ]] PID_FOLDER="$(dirname "$jarfile")"/"$PID_FOLDER"
! [[ "$LOG_FOLDER"==/* ]] LOG_FOLDER="$(dirname "$jarfile")"/"$LOG_FOLDER"
# 是否可执行?
! [[ -x "$PID_FOLDER" ]] PID_FOLDER="/tmp"
! [[ -x "$LOG_FOLDER" ]] LOG_FOLDER="/tmp"
# 设置默认值
[[ -z "$MODE" ]] MODE="{{mode:auto}}" # 模式为"auto"、"service" 或"run"
[[ -z "$USE_START_STOP_DAEMON" ]] USE_START_STOP_DAEMON="{{useStartStopDaemon:true}}"
# 为log/pid 文件创建标识
# 为日志文件和进程ID文件创建唯一标识符
if [[ -z "$identity" ]];然后
如果[[ -n "$init_script" ]];然后
身份="${init_script}"
别的
身份=$(基本名称"${jarfile%.*}")_${jarfolder////}
菲
菲
# 如果配置文件未提供,则初始化日志文件名
#日志文件目录
[[ -z "$LOG_FILENAME" ]] LOG_FILENAME="{{logFilename:${identity}.log}}"
# 如果配置文件没有提供则初始化停止等待时间
[[ -z "$STOP_WAIT_TIME" ]] STOP_WAIT_TIME="{{stopWaitTime:60}}"
#ANSIColors
echoRed() { 回显$"e[0;31m""$1"$"e[0m"; }
echoGreen() { 回显$"e[0;32m""$1"$"e[0m"; }
echoYellow() { echo $"e[0;33m""$1"$"e[0m"; }
# 实用函数
# /dev/null: 将标准错误重定向到文件/dev/null
检查权限() {
touch "$pid_file" /dev/null || { echoRed "不允许操作(无法访问pid 文件)";返回4; }
touch "$log_file" /dev/null || { echoRed "不允许操作(无法访问日志文件)";返回4; }
}
正在运行(){
ps -p "$1" /dev/null
}
等待文件(){
结束=$(日期+%s)
让"结束+=10"
尽管[[ ! -s"$1"]]
做
现在=$(日期+%s)
如果[[ $now -ge $end ]];然后
休息
菲
睡觉1
完毕
}
# 判断脚本模式
动作="运行"
if [[ "$MODE"=="auto" -n "$init_script" ]] || [[ "$MODE"=="服务" ]];然后
行动="$1"
转移
菲
#构建pid和日志文件名
PID_FOLDER="$PID_FOLDER/${身份}"
pid_file="$PID_FOLDER/{{pidFilename:${identity}.pid}}"
log_file="$LOG_FOLDER/$LOG_FILENAME"
# 确定以root身份运行的用户
# shellcheck 禁用=SC2012
# id -u 获取当前用户uid的值,$(ls -ld "$jarfile" | awk "{print $3}") 获取用户名
[[ $(id -u)=="0" ]] run_user=$(ls -ld "$jarfile" | awk "{print $3}")
# 查找Java
# 查找Java
# type命令用于显示指定命令的类型并判断给定命令是内部命令还是外部命令。
# -t:输出“file”、“alias”或“builtin”,分别表示给定的指令是“外部指令”、“命令别名”或“内部指令”;
# -p:如果给定的指令是外部指令,则显示其绝对路径;
# -a:显示环境变量“PATH”指定的路径中给定命令的信息,包括命令别名。
# "无法找到Java" 问题的根源
if [[ -n "$JAVA_HOME" ]] [[ -x "$JAVA_HOME/bin/java" ]];然后
javaexe="$JAVA_HOME/bin/java"
elif 类型-p java /dev/null 21;然后
javaexe=$(类型-p java)
elif [[ -x "/usr/bin/java" ]];然后
javaexe="/usr/bin/java"
别的
echo "无法找到Java"
1号出口
菲
#Java虚拟机参数配置,数组
参数=(-Dsun.misc.URLClassPath.disableJarChecking=true $JAVA_OPTS -jar "$jarfile" $RUN_ARGS "$@")
# 动作函数
开始() {
如果[[ -f "$pid_file" ]];然后
pid=$(cat "$pid_file")
isRunning "$pid" { echoYellow "已经在运行[$pid]";返回0; }
菲
do_start "$@"
}
# ${arguments[@]} : 使用@或*获取数组中的所有元素
开始(){
工作目录=$(目录名"$jarfile")
Pushd "$working_dir" /dev/null
mkdir -p "$PID_FOLDER" /dev/null
如果[[ -n "$run_user" ]];然后
检查权限||返回$?
chown "$run_user" "$PID_FOLDER"
chown "$run_user" "$pid_file"
chown "$run_user" "$log_file"
如果[ $USE_START_STOP_DAEMON=true ] 输入start-stop-daemon /dev/null 21;然后
启动-停止-守护进程--启动--安静
--chuid "$run_user"
--name "$identity"
--make-pidfile --pidfile "$pid_file"
--背景--不关闭
--startas "$javaexe"
--chdir "$working_dir"
-- "${参数[@]}"
"$log_file" 21
等待文件"$pid_file"
别的
su -s /bin/sh -c "$javaexe $(printf ""%s" " "${arguments[@]}") "$log_file" 21 echo $!" "$run_user" "$pid_file"
菲
pid=$(cat "$pid_file")
别的
检查权限||返回$?
"$javaexe" "${参数[@]}" "$log_file" 21
PID=$!
否认$pid
echo "$pid" "$pid_file"
菲
[[ -z $pid ]] { echoRed "启动失败";返回1; }
echoGreen "已开始[$pid]"
}
停止() {
工作目录=$(目录名"$jarfile")
Pushd "$working_dir" /dev/null
[[ -f $pid_file ]] || { echoYellow "未运行(未找到pidfile)";返回0; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoYellow "未运行(进程${pid})。正在删除过时的pid 文件。"; rm -f "$pid_file";返回0; }
do_stop "$pid" "$pid_file"
}
do_stop() {
杀死"$1" /dev/null || { echoRed "无法终止进程$1";返回1; }
for i in $(seq 1 $STOP_WAIT_TIME);做
isRunning "$1" || { echoGreen "已停止[$1]"; rm -f "$2";返回0; }
[[ $i -eq STOP_WAIT_TIME/2 ]] 杀死"$1" /dev/null
睡觉1
完毕
echoRed "无法终止进程$1";
返回1;
}
强制停止(){
[[ -f $pid_file ]] || { echoYellow "未运行(未找到pidfile)";返回0; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoYellow "未运行(进程${pid})。正在删除过时的pid 文件。"; rm -f "$pid_file";返回0; }
do_force_stop "$pid" "$pid_file"
}
do_force_stop() {
杀死-9 "$1" /dev/null || { echoRed "无法终止进程$1";返回1; }
for i in $(seq 1 $STOP_WAIT_TIME);做
isRunning "$1" || { echoGreen "已停止[$1]"; rm -f "$2";返回0; }
[[ $i -eq STOP_WAIT_TIME/2 ]] Kill -9 "$1" /dev/null
睡觉1
完毕
echoRed "无法终止进程$1";
返回1;
}
重新启动(){
停止开始
}
强制重新加载(){
工作目录=$(目录名"$jarfile")
Pushd "$working_dir" /dev/null
[[ -f $pid_file ]] || { echoRed "未运行(未找到pidfile)";返回7; }
pid=$(cat "$pid_file")
rm -f "$pid_file"
isRunning "$pid" || { echoRed "未运行(未找到进程${pid})";返回7; }
do_stop "$pid" "$pid_file"
开始
}
地位() {
工作目录=$(目录名"$jarfile")
Pushd "$working_dir" /dev/null
[[ -f "$pid_file" ]] || { echoRed "未运行";返回3; }
pid=$(cat "$pid_file")
isRunning "$pid" || { echoRed "未运行(未找到进程${pid})";返回1; }
echoGreen "正在运行[$pid]"
返回0
}
跑步() {
Pushd "$(dirname "$jarfile")" /dev/null
"$javaexe" "${参数[@]}"
结果=$?
popd /dev/null
返回“$结果”
}
# 调用适当的动作函数
案例“$action”
开始)
开始“$@”;退出$?
停止)
停止“$@”;退出$?
强制停止)
强制停止"$@";退出$?
重新启动)
重新启动“$@”;退出$?
强制重新加载)
强制重新加载"$@";退出$?
地位)
状态“$@”;退出$?
跑步)
运行“$@”;退出$?
*)
echo "Usage: $0 {start|stop|force-stop|restart|force-reload|status|run}"; 1号出口;
埃萨克
【深入解析:Spring Boot 内嵌启动脚本核心源码剖析】相关文章:
1.蛤蟆讨媳妇【哈尼族民间故事】
2.米颠拜石
3.王羲之临池学书
4.清代敢于创新的“浓墨宰相”——刘墉
5.“巧取豪夺”的由来--米芾逸事
6.荒唐洁癖 惜砚如身(米芾逸事)
7.拜石为兄--米芾逸事
8.郑板桥轶事十则
9.王献之被公主抢亲后的悲惨人生
10.史上真实张三丰:在棺材中竟神奇复活
用户评论
学习Python好久了,想尝试下 Spring Boot ,看到这个内嵌启动脚本源码挺有意思的。
有20位网友表示赞同!
之前一直想了解下 Spring Boot 的启动流程,现在有机会了!
有11位网友表示赞同!
这也太方便了吧,直接调用脚本就能启动應用程序!
有5位网友表示赞同!
代码简洁易懂,好评!
有16位网友表示赞同!
我想知道这些脚本是怎么处理环境变量的?
有9位网友表示赞同!
希望能看到更详细的解析和讲解!
有8位网友表示赞同!
内嵌启动脚本真是太棒了,开发效率大提升呀!
有18位网友表示赞同!
这能让我更深入地理解 Spring Boot 的底层实现。
有10位网友表示赞同!
分享这种资源真的很好,感谢大佬!
有10位网友表示赞同!
我需要在 linux 环境下运行,不知道这个脚本是否可以支持?
有18位网友表示赞同!
学习了这个脚本之后,我可以自己定制启动参数了吗?
有17位网友表示赞同!
我想知道这个脚本是如何与应用配置进行交互的?
有18位网友表示赞同!
这篇文章是否能够针对不同系统(如 Linux、Windows)提供不同的脚本示例?
有16位网友表示赞同!
在使用脚本的时候需要注意哪些细节?
有7位网友表示赞同!
如果想实现更复杂的启动逻辑,应该怎么做呢?
有12位网友表示赞同!
看到一些代码注释了日志输出,有没有其他详细的调试信息?
有17位网友表示赞同!
这个脚本能够支持热部署吗?
有16位网友表示赞同!
请问这个资源是否存在官方的文档或教程,方便我做更深入的学习?
有12位网友表示赞同!
希望能找到更多类似案例,用于学习和参考。
有13位网友表示赞同!
如果想要修改启动脚本的行为,应该怎么做呢?
有5位网友表示赞同!
很期待看到更多的读者分享他们的使用经验和心得!
有17位网友表示赞同!