shell启动脚本解析

327 阅读2分钟

shell启动脚本

一般启动启动脚本具有以下几个功能:

  1. 校验用户
  2. 定义变量
  3. 配置JVM参数及启动项
  4. 启动、停止、重启、查看状态等功能

代码

校验用户

checkUser() {
  if [ "`whoami`" == "root" ]; then
   echo "[Pre-Requirement]- You can't root to run this script"
   exit 1
  fi
}
checkUser

声明checkUser函数,并调用函数。 if 语句中通过 whoami 命令查询当前用户 单引号、双引号、反引号具体区别详情点击

定义变量

## 讲解见下方(1,2)
bin_path=`cd $(dirname $0); pwd`
APP_NAME=testAppName
BASE=$(dirname $bin_path)
conf=${BASE}/conf/application.yaml
log=${BASE}/conf/logback.xml
XMS=512m
XMX=1024m
profile=product
CLASS='com.test.ApplicationMain'

## 创建日志目录 ,讲解见(3)
if [ ! -d $BASE/logs ] ; then
    mkdir -p "${BASE}/logs"
fi

if [ -z "$JAVA" ] ; then
  JAVA=$(which java)
fi

if [ -z "$JAVA" ]; then
    echo "[Pre-Requirement] - Cannot find a Java JDK. Please set either set JAVA or put java (>=1.8) in your PATH." 2>&2
    exit 1
fi
if [[ $# -eq 2 ]]; then
    profile=$2
fi

有几点需要注意的:

  1. 在bash shell中, ()(反引号)都是用来做命令替换(commandsubstitution)的。只不过推荐使用()与``(反引号)都是用来做命令替换(command substitution)的。 只不过推荐使用{},因为在多重嵌套中反引号还需要通过反斜杠转义而$()不需要。 具体分析详见此链接
  2. (dirname(dirname 0) 这个命令是用来查看当前目录路径的。
  %0 为当前文件的全路径(如:/tmp/bin/run.sh)
  dirname 命令是用来获取当前文件的目录的路径的使用方式如下:
  
  命令:dirname /tmp/logs/common.log
  结果:/tmp/logs
  
  1. -d 是 文件存在且为目录;-z为字符串是否为空

判断语句if中-z至-d的意思

  1. $ 用法
$# 参数个数
$0 当前文件路径
$1 $2 $3 第一个 第二个 第三个参数

详细$用法

校验程序状态


app_status() {
## 通过启动类变量${CLASS} 查询出进程;grep invert 去掉grep进程;通过awk 解析出ps结果中的第二个:进程id
pid=`ps -ef|grep ${CLASS}|grep -v grep|awk '{print $2}'`

## grep invert去掉 空字符串; wc -l 统计行数
app_wc=`echo ${pid} | grep -v ^$ | wc -l`
if [ ${app_wc} -eq 1 ]; then
    if [ -z $1 ]; then
        echo -e "[STATUS] - $APP_NAME $pid is running ..."
    fi
    return 1
elif [ ${app_wc} -gt 1 ]; then
    echo -e "[STATUS] - $APP_NAME has $app_wc process is running !!!"
    return 2
else
    if [ -z $1 ]; then
        echo -e "[STATUS] - $APP_NAME is stopped."
    fi
    return 0
fi
}

应用启动

java_start(){
  if [[ app_status -eq 0 ]]; then
    echo "[START] - $APP_NAME starting."
    ## -e为 isFileExist;中间的-a表示且的意思,用来连接多个条件
    if [ -e ${conf} -a -e ${log} ]; then
        JAVA_OPTS="-server -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5432 -XX:-OmitStackTraceInFastThrow -Xms${XMS} -Xmx${XMX} -Xloggc:${BASE}/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE}/logs -Duser.dir=${BASE}"
        APP_OPTS="--spring.profiles.active=${profile} --spring.config.location=${conf} --logging.config=${log}"
        for i in ${BASE}/lib/*;
        ## 通过:(冒号),拼接全部jar路径
          do CLASSPATH=$i:"$CLASSPATH";
        done
        if [[ $1 -eq 0 ]]; then
            ${JAVA} ${JAVA_OPTS} -classpath .:$CLASSPATH $CLASS $APP_OPTS 1>/dev/null 2>&1 &
        elif [[ $1 -eq 1 ]]; then
            ${JAVA} ${JAVA_OPTS} -classpath .:$CLASSPATH $CLASS $APP_OPTS
        fi
        ## $!为后台运行的最后一个进程ID 
        pid=$!
        ## -n pid不为空
        if [[ -n pid ]]; then
            echo "[START] - $APP_NAME running with ${pid}"
        else
            echo "[START] - $APP_NAME running Fail..."
        fi
    else
        echo '[Pre-Requirement] - Configuration file not found!!!'
    fi
  elif [[ app_status -eq  1 ]]; then
    echo "[START] - $APP_NAME is already running."
  fi
}

停止服务

app_stop() {
if [[ app_status -eq 0 ]];then
  echo "[STOP] - $APP_NAME is not running."
  exit
fi

echo -e "[STOP] - stopping $APP_NAME $pid ... "
[ -n "$pid" ] && kill $pid

## $?为上次命令的结果(?表示问操作系统~~) 
ret=$?
waitTimes=1
while [ ${ret} = 0 -a ${waitTimes} -lt 20 ] ;do
            app_status 1
            app_status=$?
            if [[ app_status -eq 0 ]]; then
                echo -e "[STOP] - stopped app."
                break
            fi
            sleep 1
            echo -e "[STOP] - stop app ${waitTimes}th times."
            ((waitTimes--))
done
}