Linux使用脚本启动jarwar包(springboot+maven工程jar包)
作者:mmseoamin日期:2023-12-14

Linux(CentOS7)使用脚本启动java jar/war包


本文以jar包为例(war包是同样的操作流程)。


开始之前,先准备一个jar包

以springboot工程为例。

我打包用的maven。

在pom文件中可以约束最终的jar包名称:

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第1张

mvn clear 再然后 mvn install 这些都没什么好说的。


建议以下文件全部放在一个目录下

1、部署jar包

通过xftp或别的方式,将jar包放入服务器某个目录:

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第2张

2、准备application.yml(springboot工程,如果是别的框架请略过此节)

yml文件放入jar包的同一个目录,内容是常规的springboot-yml文件内容,注意yml格式:

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第3张

一会儿启动的时候会以服务器这个yml文件配置的内容为准👆👆👆

而不是项目中的yml文件👇👇👇

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第4张

3、准备jvm_opt文件(.file文件)

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第5张

此文件内容为java虚拟机启动时的参数:

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第6张

配置jvm内存:一般只改abc这三个地方:

a = b 并且 c = a*(2/3)

单位:g 或者 m

如果你怕这么配置有啥问题,你可以临时恶补一下java虚拟机的知识,反正我这儿好几个工具jar包这么配没啥问题。

VM_OPTIONS="-Xms512m -Xmx512m -Xss256K -Xmn384m -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:-UseLargePages -XX:-UseBiasedLocking"

-Xss根据你的接口或者定时任务的每次调度的数据大小,可以适当增大一些。

4、准备脚本

我这儿命名为boot.sh

先上脚本,文章后面会介绍:怎么用?脚本内容的含义?

#!/bin/bash
APP_NAME=$1
YUM_FILE_PATH=$2
[ -r jvm_opt ] && source jvm_opt   ##检查配置文件存在且可读,则将其souce
VM_OPT=${VM_OPTIONS:-Xms1g -Xmx1g -Xss256K -Xmn600m -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:-UseLargePages -XX:-UseBiasedLocking}
# 提示输入参数
usage() {
    echo app_name=$APP_NAME vm_opt=$VM_OPT yum=$YUM_FILE_PATH
    echo "Usage: ./boot.sh [APP_NAME] [YML_NAME] [start|stop|restart|status]"
    exit 1
}
# 检查程序是否在运行
is_exist(){
    # 获取PID
    PID=$(ps -ef |grep ${APP_NAME} | grep -v $0 |grep -v grep |awk '{print $2}')
    # -z "${pid}"判断pid是否存在,如果不存在返回1,存在返回0
    if [[ -z "${PID}" ]]; then
        # 如果进程不存在返回1
	echo "进程不存在"
        return 1
    else
        # 进程存在返回0
	echo "进程存在"
        return 0
    fi
}
# 启动方法
start(){
    is_exist
    if [[ $? -eq "0" ]]; then
        echo "${APP_NAME} is already running, PID=${pid}"
    else
        nohup java -jar $VM_OPT -Dspring.config.location=$YUM_FILE_PATH $APP_NAME >log 2>&1 &
		PID=$(echo $!)
        echo "${APP_NAME} start success, PID=$! YUM_FILE_PATH=${YUM_FILE_PATH}"
    fi
}
# 停止方法
stop(){
    is_exist
    if [[ $? -eq "0" ]]; then
        kill -9 ${PID}
        echo "${APP_NAME} process stop, PID=${PID}"
    else
        echo "There is not the process of ${APP_NAME}"
    fi
}
# 重启进程函数
restart(){
    stop
	echo "${APP_NAME} 准备重启..."
	sleep 5
    start
}
# 查看进程状态
status(){
    is_exist
    if [[ $? -eq "0" ]]; then
        echo "${APP_NAME} is running, PID=${PID}"
    else
        echo "There is not the process of ${APP_NAME}"
    fi
}
case $3 in
"start")
        start
        ;;
"stop")
        stop
        ;;
"restart")
        restart
        ;;
"status")
       status
        ;;
	*)
	usage
	;;
esac
exit 0

使用脚本

1、先来到你这几个文件的目录

cd /opt/tools/es-tasks

2、给脚本boot.sh赋予可执行权限:

 chmod 777 boot.sh

777是什么意思?

linux中权限是用二进制表示的。

先看一个控制台的例子:

Linux使用脚本启动jarwar包(springboot+maven工程jar包),在这里插入图片描述,第7张

看看这一列,第一个位置的 - 或者 d 这种文件描述符咱们先不用看,先从第二个位置的r开始看:

一共有9个位置 rwxrwxrwx 共三组 rwx,分别对应了 三个角色(拥有者、群组、其他人) 对这个文件或文件目录的权限。

“r - -” 就是只有【读】权限,对应二进制的 100

“- w -” 就是只有【写】权限,对应二进制的 010

“- -x” 就是只有【执行】权限,对应二进制的 001

分别翻译成十进制,“r - -” 就是400,"- w -“就是020,”- - x"就是001

那么:

如果是"rw-“就是有【读、写】权限,没有【执行】权限,对应的就是420

如果是"r-x"就是有【读、执行】权限,没有【写】权限,就是401

如果是”-wx"就是有【写、执行】权限,没有【读】权限,对应的就是021(这种设计一般不存在,都能改能执行了,就不能读吗),这里只是说明权限逻辑举例需要。

所以 “rwx” 就是421,而4+2+1=7(777就是从这来的),那么 “chmod 777 file” 这个指令的含义就是:将此文件的【读、写、执行】权限赋予给【拥有者、群组、其他人】这些角色。

当然:

1、如果你只想将此文件的【读、写、执行】权限赋予给【自己】或【自己的群组】,只需要 “chmod 700 file” 或者 “chmod 770 file” 就行。

2、 如果你只想将此文件的【读、写】权限赋予给自己或自己的群组,只需要"chmod 600 file"或者"chmod 660 file"就行了。

3、如果你想让【自己和自己组】拥有【读、写、执行】权限,而【其他人】只能【读】,只需要"chmod 774 file"。

所谓 linux权限,就这么简单。至于用户和用户组,也很简单,阁下可自行查阅其他资料学习,我就不赘述了。

请跟随我回到主题(这篇文章讲啥来着?看看标题,咱们继续)

3、执行命令

启动

./boot.sh xxx.jar application.yml start

停止

./boot.sh xxx.jar application.yml stop

重启

./boot.sh xxx.jar application.yml restart

查看是否在运行

./boot.sh xxx.jar application.yml status

脚本说明(老鸟可以略过这一节)

1、第一句

#!/bin/bash

写在 .sh 脚本文件最开头第一行。

这个是必须要写的,linux系统不同的话,写法上可能会有一丢丢区别,我这里是CentOS7。

2、第二句

APP_NAME=
YUM_FILE_PATH=

声明了两个变量,指向 $1 和 $2。

$1 对应的是咱们启动命令的:

./boot.sh xxx.jar application.yml start/stop/restart/status

其中的xxx.jar这一部分。

bash解释器是按照空格进行命令的切割,而 xxx.jar 在第【1】位置,所以是$1 (第【0】位置是 ./boot)。

$2同理。

这两句话的意思就是,声明这俩变量,并且让APP_NAME=xxx.jar,让YUM_FILE_PATH=application.yml

3、第三句和第四句

[ -r jvm_opt ] && source jvm_opt

检查这个jvm_opt文件,如果存在并且可读,就把它的内容加载进来。

VM_OPT=${VM_OPTIONS:-Xms1g -Xmx1g -Xss256K -Xmn600m -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:-OmitStackTraceInFastThrow -XX:+AlwaysPreTouch -XX:-UseLargePages -XX:-UseBiasedLocking}

声明一个VM_OPT变量,让它等于后面这个${VM_OPTIONS : …},这里面的VM_OPTIONS就是从jvm_opt文件中取出来的变量。

意思是:如果取到了,就让VM_OPT=VM_OPTIONS,如果没取到,就让VM_OPT等于冒号后面的这一长串值。

4、接下来就是六个自定义方法(也叫函数)

第一个方法,用于提示
usage() {
    echo app_name=$APP_NAME vm_opt=$VM_OPT yum=$YUM_FILE_PATH
    echo "Usage: ./boot.sh [APP_NAME] [YML_NAME] [start|stop|restart|status]"
    exit 1
}

此方法在脚本被非正常执行时触发,比如说你./boot.sh start就想执行,xxx.jar也不写

那它就提示你 “Usage: ./boot.sh [APP_NAME] [YML_NAME] [start|stop|restart|status]” 一个正常命令格式是什么。

第二个方法,用于判断是否已经在运行
is_exist(){
    # 获取PID
    PID=$(ps -ef |grep ${APP_NAME} | grep -v 
第三个方法,用于启动jar包
|grep -v grep |awk '{print }') # -z "${pid}"判断pid是否存在,如果不存在返回1,存在返回0 if [[ -z "${PID}" ]]; then # 如果进程不存在返回1 echo "进程不存在" return 1 else # 进程存在返回0 echo "进程存在" return 0 fi }
第四个方法,用于停止jar包
start(){
    is_exist
    if [[ $? -eq "0" ]]; then
        echo "${APP_NAME} is already running, PID=${pid}"
    else
        nohup java -jar $VM_OPT -Dspring.config.location=$YUM_FILE_PATH $APP_NAME >log 2>&1 &
                PID=$(echo $!)
        echo "${APP_NAME} start success, PID=$! YUM_FILE_PATH=${YUM_FILE_PATH}"
    fi
}

其中,"is_exist"是调用了上面讲的第二个方法。

然后拿着 is_exist() 方法运行的结果(0或者1)来决定要不要启动。

这一段脚本总体意思也很简单,判断进程是否已经存在,如果存在就提示;不存在就静默启动,启动完了提示success。

其中:

nohup java -jar $VM_OPT -Dspring.config.location=$YUM_FILE_PATH $APP_NAME >log 2>&1 &

这一段就是在启动了。 “>” 代表输出,log代表同级目录下的日志文件log.file,如果启动后log文件不存在则会自动创建。

">log"意思是把程序的输出内容写到log这个文件中去。

顺便提一嘴奥

一个 > 号 “>”

会把之前的覆盖掉,也就是说,每次重启jar包,之前log中的内容就没了。

好处也很明显,不会造成文件膨胀,排查本次启动后问题时也会很方便。

两个 > 号 “>>”

在之前的文件内容的基础上,不断追加新的内容。

我springboot工程一般都用到日志框架,这些框架会把日志,按日期写入某个文件夹内的一个个文件中去,所以我一般脚本这个位置写 一个">“符号,也就是”>log"

继续看这段脚本:

nohup java -jar $VM_OPT -Dspring.config.location=$YUM_FILE_PATH $APP_NAME >log 2>&1 &

“2>&1” 意思是 把程序的 标准错误输出 也重定向到 标准输出。

在linux中,标准输入用0表示,标准输出用1表示,标准错误输出用2表示。

最后一个 “&” 代表静默启动,“别占用我控制台一直打印” 就这个意思。

stop(){
    is_exist
    if [[ $? -eq "0" ]]; then
        kill -9 ${PID}
        echo "${APP_NAME} process stop, PID=${PID}"
    else
        echo "There is not the process of ${APP_NAME}"
    fi
}
第五个方法,用于重启jar包

非常好理解:进程存在否?存在就杀掉进程然后提示;不存在就直接提示。

restart(){
    stop
        echo "${APP_NAME} 准备重启..."
        sleep 5
    start
}
第六个方法,查看运行状态

也很好理解:先停止,睡5秒,再启动。

status(){
    is_exist
    if [[ $? -eq "0" ]]; then
        echo "${APP_NAME} is running, PID=${PID}"
    else
        echo "There is not the process of ${APP_NAME}"
    fi
}

脚本的最后一段

这个就不用说了,只是调用了一下 is_exist() 方法然后根据0或1的返回,给我们提示运行状态而已。

case  in
"start")
        start
        ;;
"stop")
        stop
        ;;
"restart")
        restart
        ;;
"status")
       status
        ;;
        *)
        usage
        ;;
esac
exit 0

jar包运行后的log日志怎么看?

前面讲过,$3就是咱们启动命令:

./boot.sh xxx.jar application start/stop/restart/status

其中的 start / stop / restart / status 这个部分。

脚本根据我们输入的其中一个选项,执行不同的方法。

" *)usage ;; " 的意思是我们输入的东西不在【start / stop / restart / status】这个范围内,就会走 usage() 方法,也就是提示我们正常的格式。

“esac” 就是 “case” 反过来写,是脚本中的一种语法,类似于【 " if " 与 " fi "】。

“exit 0” 意思是运行正常退出脚本程序。

tail -100f log

我一般用这几个命令

1、实时查看100行日志

more log

2、搜索日志中内容

写在最后

然后敲 “/”

再然后输入你要搜索的内容,回车。

如果输入错了,按 ctrl + backspace(退格) 往前删。

diy举例

简单好用,相当于一个雏形,支持高度diy。

但是要小心,别在脚本中写自己拿不准的指令。

vi boot.sh

比如说你就想用springboot工程resources下的那个yml配置,不愿意把它提取出来,脚本改起来也很简单,只要找到 $, 把 $ 后面的数字改成你命令中对应的位置就ok。

比如:

先删掉 YUM_FILE_PATH=$2 这个变量(所有引用到这个变量的地方也给改改好奥)

把脚本最后的

case $3 in …

其中的$3

改成你 start/stop/restart/status 这个指令的位置

假如说你指令是这么写的:

./boot.sh xxx.jar start

那就把./boot.sh脚本中的所有 $3 改成 $2。

很明显嘛,你变短了,数字也就变少了。

话说回来,稍微有点规模的项目一般也用不着这玩意,docker、k8s集群部署会更省心。

就有时候一些工具类的小玩意用一下还是蛮不错的。


ok,完活!