springboot自启动脚本shell、systemctl以及service文件Environment用法

springboot通用管理脚本

在springboot打包成jar包之后,往往需要很多启动参数辅助服务启动,为了避免每次都写很长的启动命令,可以将这些重复性工作写成脚本。

shell脚本:

#!/bin/bash
# jar包的名字
APP_NAME=appname
# 环境配置文件,如application-dev.yml
PROFILE=dev
JAR_NAME=$APP_NAME\.jar
PID=$APP_NAME\.pid
PROJ_HOME=$(pwd)
# 这个是jar包的路径需要根据自己的情况配置
APP_HOME=$PROJ_HOME/target
LOG_PATH=$APP_HOME/logs
# 创建log路径
if [ ! -d $LOG_PATH ]; then
  mkdir $LOG_PATH
fi
# GC日志参数
GC_LOG_OPTS=" -XX:+PrintGC -XX:+PrintGCDetails -Xloggc:$LOG_PATH/gc-%t.log"
# GC收集器参数
GC_OPTS="-XX:+UseConcMarkSweepGC"
# 其他参数
OTHER_OPTS="-Dspring.profiles.active=$PROFILE"
# JVM 启动参数
JVM_OPTIONS="-server -Xms64m -Xmx64m -XX:MetaspaceSize=16m $GC_OPTS $GC_LOG_OPTS $OTHER_OPTS"
# 使用说明,用来提示输入参数
usage() {
  echo "Usage: demogc.sh [start|stop|restart|status]"
  exit 1
}
# 检查程序是否在运行
is_exist() {
  pid=$(ps -ef | grep $APP_HOME/$JAR_NAME | grep -v grep | awk '{print $2}')
  #如果不存在返回1,存在返回0
  if [ -z "${pid}" ]; then
    return 1
  else
    return 0
  fi
}
# 启动方法
start() {
  is_exist
  if [ $? -eq "0" ]; then
    echo "WARN: $JAR_NAME is already running PID=${pid}"
  else
    echo "JVM_OPTIONS : "
    echo $JVM_OPTIONS | sed 's/ /\n/g '
    nohup java -jar $JVM_OPTIONS $APP_HOME/$JAR_NAME >>$LOG_PATH/stdout.log 2>&1 &
    echo $! >$PID
    echo "INFO: start $JAR_NAME successed PID=$!"
  fi
}
# 停止方法
stop() {
  #is_exist
  pidf=$(cat $PID)
  echo "INFO: app PID = $pidf begin kill $pidf"
  kill "$pidf"
  rm -rf $PID
  sleep 2
  is_exist
  if [ $? -eq "0" ]; then
    echo "INFO: app 2 PID = ${pid} begin kill -9 ${pid}"
    kill -9 ${pid}
    sleep 2
    echo "INFO: $JAR_NAME process stopped ---"
  else
    echo "INFO: $JAR_NAME is not running ---"
  fi
}
# 输出运行状态
status() {
  is_exist
  if [ $? -eq "0" ]; then
    echo "INFO: $JAR_NAME is running PID is $pid"
  else
    echo "WARN: $JAR_NAME is not running"
  fi
}
# 重启
restart() {
  stop
  start
}

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

这种写法也是CentOS7之前服务文件的写法,CentOS7时候就采用了systemd服务,所以也可以写成systemctl的service文件形式

systemctl服务:

1.在写systemd服务时可以借助上面写好的shell脚本

[Unit]
Description=demo - demo server
Documentation=http://git.demo.com/demo
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
User=root
ExecStart=/bin/sh -c '/home/codes/java/demo/demo.sh start'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/sh -c '/home/codes/java/demo/demo.sh stop'

[Install]
WantedBy=multi-user.target

2.也可以不借助上面的shell脚本,使用systemctl的写法来写服务

[Unit]
Description=demo - demo server
Documentation=http://git.demo.com/demo
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
User=root
Environment="JAR_NAME=demogc-1.0.0.jar"
Environment="PROFILE=dev"
Environment="PROJ_HOME=/home/codes/java/demogc"
Environment="APP_HOME=$PROJ_HOME/target"
Environment="LOG_PATH=$PROJ_HOME/logs"

Environment="GC_LOG_OPTS=-XX:+PrintGC -XX:+PrintGCDetails -Xloggc:/home/codes/java/demogc/logs/demogc.log"
Environment="GC_OPTS=-XX:+UseConcMarkSweepGC"
Environment="OTHER_OPTS=-Dspring.profiles.active=dev"
Environment="JVM_OPTIONS=-server -Xms64m -Xmx64m -XX:MetaspaceSize=16m $GC_OPTS $GC_LOG_OPTS $OTHER_OPTS"


ExecStartPre=/bin/sh -c 'if [ ! -d ${LOG_PATH} ]; then mkdir ${LOG_PATH}; fi'
ExecStart=/bin/sh -c 'java ${JVM_OPTIONS} -jar ${APP_HOME}/${JAR_NAME} >${LOG_PATH}/stdout.log  2>&1 &'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy=multi-user.target

因为涉及变量和创建路径,这里会用到EnvironmentExecStartPre

但是这里有个问题,环境变量太多看着乱,每次有修改还需要改service问题件,而且-Xloggc这个参数中不能再引入$变量,在Exec*中无法解析这个变量。所以可以才用EnvironmentFile的形式将变量独立一个文件出来。

3.借助EnvironmentFile来引入变量(或环境变量)

先将所有变量提取到demo.env中

JAR_NAME=demogc-1.0.0.jar
PROFILE=dev
PROJ_HOME=/home/codes/java/demogc
APP_HOME=$PROJ_HOME/target
LOG_PATH=$PROJ_HOME/logs

GC_LOG_OPTS="-XX:+PrintGC -XX:+PrintGCDetails -Xloggc:$LOG_PATH/gc.log"
GC_OPTS=-XX:+UseConcMarkSweepGC
OTHER_OPTS=-Dspring.profiles.active=dev
JVM_OPTIONS="-server -Xms64m -Xmx64m -XX:MetaspaceSize=16m $GC_OPTS $GC_LOG_OPTS $OTHER_OPTS"

修改demo.service文件

[Unit]
Description=demo - demo server
Documentation=http://git.demo.com/demo
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
User=root
EnvironmentFile=/home/codes/java/demogc/demo.env

ExecStartPre=/bin/sh -c 'if [ ! -d ${LOG_PATH} ]; then mkdir ${LOG_PATH}; fi'
ExecStart=/bin/sh -c 'java ${JVM_OPTIONS} -jar ${APP_HOME}/${JAR_NAME} >${LOG_PATH}/stdout.log  2>&1 &'
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy=multi-user.target

这样service文件就清晰了很多

总结

1.注意${DEMO}$DEMO的区别,shell命令执行的时候会将$DEMO中的$符号继续解析为变量所代表的值,而使用${DEMO}会将里面所有的字符包括$都原封不动的当成字符不解析

2.注意Environment中即便带空格可以不用引号在包起来,如Environment="DEMO=a b",不用写成Environment='DEMO="a b"'

3.EnvironmentFile可以将环境变量独立出一个单独的文件,并且在$嵌套的情况下不会出现问题

你可能感兴趣的:(Java,SpringBoot)