1、前言

在实际的开发或生产环境中,服务器可能会宕机或者被人为重启。这时我们部署在这台服务器上的java服务就会停掉。我通过下文来说明如何解决这一问题。

2、具体流程

2.1、材料准备

我们需要准备一个文件夹,下面放上我的的springboot工程打好的jar包和我们的shell脚本。如下图所示(log是执行run.sh后自动生成的)

run.sh脚本已经上传到了csdn的资料库springboot工程jar包启动脚本-Java文档类资源-CSDN下载。也可以拷贝下面的脚本内容

#!/bin/bash
# log format function
function log(){
   loglevel="$1"
   shift
   if [ "$1" ];then case "$loglevel" in
       debug)
          ;; # echo -e "\033[35m[$(date "+%Y-%m-%d %H:%M:%S")] [DEBUG]\t${@}\033[0m" ;;
       info)
          echo -e "\033[32m[$(date "+%Y-%m-%d %H:%M:%S")] [INFO]\t${@}\033[0m" ;;
       warning)
          echo -e "\033[33m[$(date "+%Y-%m-%d %H:%M:%S")] [WARNING]\t${@}\033[0m" ;;
       error)
          echo -e "\033[31m[$(date "+%Y-%m-%d %H:%M:%S")] [ERROR]\t${@}\033[0m" ;;
       *)
          echo "${@}" ;;
     esac
   fi
}

# Load environment variables
if [ -f "/etc/profile" ]; then
   log debug "从 [/etc/profile] 加载环境变量."
   . /etc/profile
fi
if [ -f "$HOME/.bash_profile" ]; then
   log debug "从 [$HOME/.bash_profile]加载环境变量."
   . $HOME/.bash_profile
fi
if [ -f "$HOME/.bashrc" ]; then
   log debug "从 [$HOME/.bashrc]加载环境变量."
   . $HOME/.bashrc
fi

# Verify that the service is running as a normal user
if [ "$(whoami)" == "root" ]; then
   log warning "不推荐使用 [$(whoami)] 用户运行应用服务."
fi

# Verify the java command, otherwise exit directly
if [ ! "$(command -v java)" ];then
   log error "未找到java命令,必须先安装JDK或JRE并配置环境变量."; exit 1
fi

# Switch working directory and define variables
cd $(dirname $0)
basedir="$(pwd -P)"
jarfile="$(find $basedir -maxdepth 1 -type f -name "*.jar")"
jarnums="$(find $basedir -maxdepth 1 -type f -name "*.jar"|wc -l)"
logfile="$basedir/log/application.log"
logconf="$basedir/log/logrotate.cnf"
logstat="$basedir/log/logrotate.status"
jarback="$basedir/backup"

log debug  "basedir: [$basedir]"
log debug  "jarfile: [$jarfile]"
log debug  "jarnums: [$jarnums]"
log debug  "logfile: [$logfile]"
log debug  "logconf: [$logconf]"
log debug  "jarback: [$jarback]"

# check jar file exists
function check(){
   if [ "$jarnums" -lt "1" ];then
      log error "目录 [${basedir}] 下未找到.jar文件."; exit 1
   elif [ "$jarnums" -gt "1" ];then
      log warning "目录 [${basedir}] 下.jar文件不唯一"; exit 1
   else
      pid="$(ps -aux|grep "java"|grep "$jarfile"|grep -v "grep"|awk '{print $2}'|tr '\n' ' ')"
   fi
}

# status function
function status(){
   check
   if [ "$pid" ];then
      log info "应用服务 [$(basename $jarfile)] 状态: 运行中,PID:[ $pid]."
   else
      log info "应用服务 [$(basename $jarfile)] 状态: 未运行."
   fi
}

# start function
function start(){
   check
   if [ "$pid" ];then
      log warning "应用服务 [$(basename $jarfile)] 已经在运行中, PID: [ $pid]."
   else
      log info "应用服务 [$(basename $jarfile)] 正在启动..."
      log debug "创建应用服务日志目录"
      log debug "mkdir -p $basedir/log"
      mkdir -p "$basedir/log"
      log debug "nohup $(command -v java) -Xms256M -Xmx512M -jar $jarfile $@ >> $logfile 2>&1 &"
      nohup $(command -v java) -Xms256M -Xmx512M -jar $jarfile $@ >> $logfile 2>&1 &
      pid="$!"
      if [ "$pid" ];then
         log debug "应用服务 日志轮转开始."
         log debug "(while kill -0 $pid;do rotate;sleep 60;done) > /dev/null 2>&1 &"
         (while kill -0 $pid;do rotate;sleep 60;done) > /dev/null 2>&1 &
         log info "应用服务 [$(basename $jarfile)] 启动完成,PID: [ $pid ]"
         log warning "应用服务 [$(basename $jarfile)] 日志输出将在30秒后自动退出."
         sleep 3
         log debug "应用启动日志: tail -1f $logfile &"
         tail -1f $logfile &
         (sleep 30 && kill $!) > /dev/null 2>&1 &
         log debug "(sleep 60 && kill $!) > /dev/null 2>&1 &"
      fi
   fi
}

# stop function
function stop(){
   check
   if [ "$pid" ];then
      log info "应用服务 [$(basename $jarfile)] 停止中..."
      log debug "kill -9 $pid"
      kill -9 $pid > /dev/null 2>&1
      sleep 2 && echo
      log debug "应用服务 [$(basename $jarfile)] 已经停止"
   else
      log warning "应用服务 [$(basename $jarfile)] 似乎没有在运行,不需要停止"
   fi
}

# restart function
function restart(){
   stop
   sleep 2
   start "$@"
}


# console start function
function console(){
   check
   if [ "$pid" ];then
      log warning "应用服务 [$(basename $jarfile)] 已经在运行中, PID: [ $pid]."
   else
      log info "应用服务 [$(basename $jarfile)] 正在启动..."
      log warning "console 参数仅用于调试, 使用 [Ctrl + C] 终止调试进程."
      log debug "创建应用服务日志目录"
      log debug "mkdir -p $basedir/log"
      mkdir -p "$basedir/log"
      sleep 2
      log debug "cd $basedir && $(command -v java) -Xms256M -Xmx512M -jar $jarfile $@ 2>&1 | tee $logfile"
      cd $basedir && $(command -v java) -Xms256M -Xmx512M -jar $jarfile $@ 2>&1 | tee $logfile
   fi
}

# rotate function
function rotate(){
   log debug "创建应用服务日志目录"
   log debug "mkdir -p $basedir/log"
   mkdir -p "$basedir/log"
   if [ ! -e $logconf ];then
      log warning "日志轮转配置文件 [${logconf}] 不存在, 将创建此配置文件."
      log debug "${logfile} {\n  size 32M\n rotate 16\n  compress\n  missingok\n  dateext\n  dateformat -%Y%m%d-%s\n  copytruncate\n}"
      echo -e "${logfile} {\n  size 32M\n rotate 16\n  compress\n  missingok\n  dateext\n  dateformat -%Y%m%d-%s\n  copytruncate\n}" > $logconf
   fi
   if [ -e $logfile ];then
      log info "归档并压缩应用服务日志 [${logfile}]"
      log debug "/usr/sbin/logrotate -s $logstat $logconf"
      /usr/sbin/logrotate -s $logstat $logconf
      log info "归档并压缩日志文件 ${logfile} 完成."
      log debug "使用 [ll -h ${logfile}*] 命令查看归档日志文件"
   fi
}

# backup function
function backup(){
   if [ ! -d "$jarback" ];then
      log warning "创建jar包备份目录 [$jarback]"
      log debug "mkdir -p $jarback"
      mkdir -p $jarback
   fi
   jarbasename="$(basename $jarfile)"
   jarbackname="${jarbasename%.*}-$(date "+%Y%m%d-%H%M%S").${jarbasename##*.}"
   log debug "应用服务 备份jar包目录 [$jarback]"
   log debug "应用服务 备份jar包名称 [$jarback/$jarbackname]"
   log info "备份jar包文件 [$jarfile]"
   log info " ==> jar包备份目录 [$jarback]"
   cp $basedir/$jarbasename $jarback/$jarbackname
}

# help
function help(){
   log "" "使用说明:"
   log "" " $0 {start|stop|status|restart|console|backup|rotate} [options]"
   log "" " [options] : "
   log "" "   --spring.config.location=app.yml,app-ext.yml  # 指定服务配置文件为: app.yml,app-ext.yml"
   log "" "   --spring.profiles.active=development          # 指定服务配置环境为: development"
   log "" "   --server.port=8888                            # 指定服务配置端口为: 8888"
   log "" "   --server.servlet.context-path=/test           # 指定服务配置路径为: /text"
}

act="$1"
shift
arg="$(echo "$@"|sed 's/[ ]*=[ ]*/=/g')"

log debug "Script parameters [ $act ]"

case "$act" in
   start)
      start $arg ;;
   stop)
      stop ;;
   restart)
      restart $arg ;;
   status)
      status ;;
   rotate )
      rotate ;;
   console)
      console $arg ;;
   backup)
      backup ;;
   *)
    start $arg ;;
esac

exit 0

2.2、修改开机启动项配置

找到rc.local 脚本,一般在这个目录下

cd /etc/rc.d

在rc.local添加run.sh脚本的绝对路径,就可以了

 3、注意

run.sh和rc.local文件都要设置为可执行文件

chmod 755 run.sh

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐