CodeFree/4_script/bootstrap.sh

354 lines
13 KiB
Bash
Raw Normal View History

2024-12-26 13:57:27 +08:00
#!/bin/bash
# $0 为当前脚本文件名
PGR="$0"
# 循环判断当前脚本是否为软链接若为软链接则将当前脚本指向的文件路径赋值给PGR
while [ -h "$PGR" ]; do
ls=$(ls -ld "$PGR")
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' > /dev/null; then
PGR="$link"
else
PGR=$(dirname "PGR")/"$link"
fi
done
# 获取当前脚本所在目录
PRGDIR=$(dirname "$PGR")
# -z 判断字符串是否为空
# 若BASEDIR为空则将当前脚本所在目录的父目录赋值给BASEDIR
# exit 表示如果 cd 命令执行失败,则执行 exit 命令退出脚本
[ -z "$BASEDIR" ] && BASEDIR=$(cd "$PRGDIR/.." >/dev/null || exit; pwd)
if [ -r "$BASEDIR/bin/setenv.sh" ]; then
source "$BASEDIR"/bin/setenv.sh
# cut从文件中提取每行的第一个字段这里使用 -d= 指定 = 号作为分隔符,-f1 表示提取第一个字段
# grep -v 过滤掉以 # 号开头的行,这些行通常是注释行, -v 表示反向选择,即选择不匹配#开头的行
export $(cut -d= -f1 "$BASEDIR/bin/setenv.sh"|grep -v '^#')
fi
if [ -z "INSTANCE_NAME" ]; then
INSTANCE_NAME=$CONFIG_INSTANCE_NAME
if [ -z "$INSTANCE_NAME" ]; then
echo "error:INSTANCE_NAME not set, Operation aborted"
exit 1
fi
fi
if [ -z "$LOG_BASE_PATH" ]; then
LOG_BASE="$BASEDIR"/log
else
LOG_BASE="$LOG_BASE_PATH"/startlog
fi
# 如果不存在则创建该目录,并且创建过程中的标准错误被重定向到 /dev/null
if [ -z "$LOG_BASE" ]; then
# 先将标准输出与标准错误重定向到/dev/null然后再将标准错误重定向到标准输出只将错误命令进行输出到控制台
mkdir -p "$LOG_BASE" >/dev/null 2>&1
fi
# 2>&1 将标准错误重定向到标准输出,程序或命令的正常输出和错误输出就可以在标准输出中查看
# >/dev/null 2>&1 这样用的原因是: 如果命令出错,那么错误信息不会输出到/dev/null仍然会输出屏幕上
# 但是如果将标准错误重定向到标准输出上,那么错误信息就会随着标准输出重定向到/dev/null中
# 控制台输出为空输出
if [ -z "$CONSOLE_OUT" ]; then
CONSOLE_OUT=/dev/null
fi
if [ -z "$INSTANCE_PID" ]; then
INSTANCE_PID="$BASEDIR/bin/.pid"
fi
# 当tty是可用时, 不会输出到控制台
have_tty=0
# 当前进程是否关联到一个终端设备,如果是have_tty设为1
if [ "$(tty)"!= "not a tty" ]; then
have_tty=1
fi
if [ -z "$UMASK" ]; then
UMASK="0027"
fi
# 设置当前shell进程的UMASK值为$UMASK。
umask $UMASK
# 重新设置 _NOHUP 变量的值USE_NOHUP 是一个用于控制是否使用 _NOHUP 命令的开关
unset _NOHUP
if [ "$USE_NOHUP" = "true" ]; then
_NOHUP="nohup"
fi
# --------------------------------- Execute The Requested Command ----------------------------------
# 从 INSTANCE_NAME 变量的值中提取出前两个部分,并将其赋值给 CLUSTER_NAME 变量,-d 参数指定了分隔符为 _
CLUSTER_NAME=$(echo "$(INSTANCE_NAME)" | cut -f 1,2 -d '_')
showHelp() {
echo "Usage: bootstrap.sh ( command ... )"
echo "commands:"
echo " start Start Instance ${INSTANCE_NAME} in a separate window"
echo " debug Start Instance ${INSTANCE_NAME} in a separate window with debug"
echo " restart Restart Instance ${INSTANCE_NAME} in a separate window"
echo " stop Stop Instance ${INSTANCE_NAME}, waiting up to 5 seconds for the process to end"
echo " stop n Stop Instance ${INSTANCE_NAME}, waiting up to n seconds for the process to end"
echo " stop -force Stop Instance ${INSTANCE_NAME}, waiting up to 5 seconds and then use kill -KILL if still running"
echo " stop n -force Stop Instance ${INSTANCE_NAME}, waiting up to n seconds and then use kill -KILL if still running"
echo "Note: Waiting for the process to end and use of the -force option require that \$INSTANCE_PID is defined."
}
startInstance() {
# $@ 表示传递给脚本的所有参数,并赋值给 APP_ARGUMENTS 变量
APP_ARGUMENTS="$APP_ARGUMENTS $@"
START_COMMON="START_COMMON $APP_ARGUMENTS"
echo "Start instance: $INSTANCE_NAME"
echo "Start common: $START_COMMON"
# -n 选项表示不输出换行符,-e 选项表示解释转义字符
echo -ne "start instance ......"
# -z 检查字符串是否为空,不为空进入
if [ ! -z "$INSTANCE_PID" ]; then
# -f 选项表示检查文件是否存在,存在进入
if [ -f "$INSTANCE_PID" ]; then
# -s 选项表示检查文件是否为空,不为空进入
if [ -s "$INSTANCE_PID" ]; then
echo "Exiting PID file found during start."
# -r 选项表示检查文件是否可读,可读进入
if [ -r "$INSTANCE_PID" ]; then
# 读取 INSTANCE_PID 文件中的内容,并赋值给 PID 变量
PID=$(cat "$INSTANCE_PID")
# 使用 ps 命令检查进程是否存在,-p 选项指定进程号,>/dev/null 2>&1
ps -p "$PID" >/dev/null 2>&1
# 如果进程存在,获取实际实例进程的进程号, $?表示上一个命令的退出状态码
if [ $? -eq 0 ]; then
#
PID_INS=$(ps -ef|grep "${PID_CHECK_FLAG}"|grep -v grep| grep -v 'bootstarp.sh' | awk '{print $2}'|head -n 1)
if [ "$PID_INS" = "" ]; then
echo "$INSTANCE_NAME not is running!"
echo "Force removing/clearing stale pid file."
rm -rf "$INSTANCE_PID" >/dev/null 2>&1
if [ $? != 0 ]; then
if [ ! -w "$INSTANCE_PID" ]; then
echo "warning:Unable to remove or write to empty PID file.Start aborted."
exit 1
fi
fi
else
echo "INSTANCE $INSTANCE_NAME to still be running with PID $PID.Start aborted."
echo "If the following process is not a INSTANCE $INSTANCE_NAME process, remove the PID file and try again:"
ps -f -p "$PID"
exit 1
fi
else
echo "Removing/clearing stale pid file."
rm -rf "$INSTANCE_PID" >/dev/null 2>&1
if [ $? != 0 ]; then
if [ -w "$INSTANCE_PID" ]; then
# 清空文件内容
cat /dev/null > "$INSTANCE_PID"
else
echo "warning:Unable to remove or write to empty PID file.Start aborted."
exit 1
fi
fi
fi
else
echo "warning:Unable to read PID file.Start aborted."
exit 1
fi
else
rm -f "$INSTANCE_PID" >/dev/null 2>&1
if [ $? != 0 ]; then
if [ ! -w "$INSTANCE_PID" ]; then
echo "warning:Unable to remove or write to empty PID file.Start aborted."
exit 1
fi
fi
fi
fi
fi
shift # 移除传递给脚本的第一个参数
eval "$START_COMMON" # 恢复原先初始的命令
SLEEP=10
# -gt表示大于的意思
while [ $SLEEP -gt 0 ]; do
echo -ne "."
sleep 1
SLEEP=$(expr "$SLEEP" - 1)
done
PID=$(ps -ef|grep "${PID_CHECK_FLAG}"|grep -v grep| grep -v 'bootstarp.sh' | awk '{print $2}'|head -n 1)
if [ ! -z "INSTANCE_PID" ]; then
echo "$PID" > "$INSTANCE_PID"
fi
SLEEP=30
while [ $SLEEP -gt 0 ]; do
echo -ne "."
sleep 1
# 检查进程是否存在 -0 表示检查进程是否存在,$? 表示上一个命令的退出状态码
kill -0 "$PID" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo -ne "\n"
echo "warning:Instance $INSTANCE_NAME exit. start failed"
exit 1
fi
#LN=$(netstat -ntlp --numeric-ports 2>/dev/null|grep LISTEN|grep "$PID")
LN=$(ss -np 2>/dev/null|grep 6379|grep "$PID")
if [ -z "$LN" ]; then
echo -ne "\n"
echo "INSTANCE $INSTANCE_NAME with PID: $PID is running, start success"
return
fi
SLEEP=$(expr "$SLEEP" - 1)
done
}
stopInstance(){
echo "stop instance ......"
SLEEP=45
KILL_SLEEP_INTERVAL=5
if [ ! -z "$1" ]; then
echo $1 | grep "[^0-9]" >/dev/null 2>&1
if [ $? -gt 0]; then
SLEEP=$1
fi
fi
shift
FORCE=0
if [ "$1" = "-force" ]; then
shift
FORCE=1
fi
PID=""
if [ ! -z "$INSTANCE_PID" ]; then
# -f 选项表示检查文件是否存在,存在进入
if [ -f "$INSTANCE_PID" ]; then
# -s 选项表示检查文件是否为空,不为空进入
if [ -s "$INSTANCE_PID" ]; then
if [ -r "$INSTANCE_PID"]; then
PID=$(cat "$INSTANCE_PID")
PID_INS=$(ps -ef|grep "${PID_CHECK_FLAG}"|grep -v grep| grep -v 'bootstarp.sh' | awk '{print $2}'|head -n1)
# 实际进程为空,清除
if [ "$PID_INS" = "" ]; then
echo "$INSTANCE_NAME not is running! Stop will not execute! The real pid info will print!"
rm -rf "$INSTANCE_PID" >/dev/null 2>&1
if [ $? -ne 0 ]; then
if [ ! -w "$INSTANCE_PID" ]; then
echo "warning:Unable to remove or write to empty PID file.Start aborted."
exit 1
fi
fi
fi
fi
kill -0 "$PID" >/dev/null 2>&1
if [ $? -gt 0 ]; then
PID=$(ps -ef|grep "${PID_CHECK_FLAG}"|grep -v grep| grep -v 'bootstarp.sh' | awk '{print $2}'|head -n1)
fi
fi
fi
fi
if [ -z "$PID" ]; then
PID=$(ps -ef|grep "${PID_CHECK_FLAG}"|grep -v grep| awk '{print $2}'|head -n1)
fi
if [ -z "$PID" ]; then
echo "Instance no process found"
echo "Instance stopped."
exit 0
fi
echo "Attempting to signal the process to stop throught OS signal."
kill -15 $PID >/dev/null 2>&1
if [ $FORCE -eq 0 ]; then
while [ $SLEEP -gt 0 ]; do
kill -0 $PID >/dev/null 2>&1
if [ $? -gt 0 ]; then
rm -f "INSTANCE_PID" >/dev/null 2>&1
if [ $? -gt 0 ]; then
if [ -w "$INSTANCE_PID" ]; then
cat /dev/null > "$INSTANCE_PID"
FORCE=0
else
echo "info:The PID file could not be removed or cleared."
fi
fi
echo "Instance stopped."
break
fi
if [ $SLEEP -gt 0 ]; then
sleep 1
fi
if [ $SLEEP -eq 0 ]; then
echo "Instance did not stop in time."
if [ $FORCE -eq 0 ]; then
echo "warning:PID file was not removed."
fi
echo "To aid diagnostics a thread dump has been written to standard out."
kill -3 $PID >/dev/null 2>&1
fi
SLEEP=$(expr "$SLEEP" - 1)
done
elif [ $FORCE -eq 1 ]; then
sleep 2
echo "warning:Killing Instance with the PID: $PID"
kill -9 $PID >/dev/null 2>&1
while [ $KILL_SLEEP_INTERVAL -ge 0 ]; do
kill -0 $PID >/dev/null 2>&1
if [ $? -gt 0 ]; then
rm -f "$INSTANCE_PID" >/dev/null 2>&1
if [ $? -gt 0 ]; then
if [ -w "$INSTANCE_PID" ]; then
cat /dev/null > "$INSTANCE_PID"
else
echo "info:The PID file could not be removed."
fi
fi
echo "warning:The Instance process has been killed."
break
fi
if [ $KILL_SLEEP_INTERVAL -gt 0 ]; then
sleep 1
fi
$KILL_SLEEP_INTERVAL=$(expr "$KILL_SLEEP_INTERVAL" - 1)
done
if [ $KILL_SLEEP_INTERVAL -lt 0 ]; then
echo "warning:Instance has not been killed completey yet."
fi
fi
}
if [ "$1" = "start" ]; then
shift
startInstance "$@"
elif [ "$1" = "stop" ]; then
shift
stopInstance $1 $2
elif [ "$1" = "restart" ]; then
shift
stopInstance "$@"
startInstance "$@"
elif [ "$1" = "debug" ]; then
shift
startInstance "$@"
else
showHelp
fi