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