#!/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