前言

最近在部署Spring Boot构建的Api
因为有多个jar要启动,启动的参数也都不一样 不高兴.png
搞的我都蛋疼了,只好研究下使用shell脚本来一键管理了
花了两个小时,终于把脚本撸出来了 太开心.png
注意如果在windows下创建shell脚本文件,注意文档格式要转换为unix才能在linux中运行
推荐直接在linux中直接使用vi创建shell脚本文件

创建脚本

在指定路径下运行vi startAll.sh来创建脚本文件
参考如下代码:

#!/bin/sh
## java安装目录
export JAVA_HOME=/usr/java/jdk1.8
export JRE_HOME=$JAVA_HOME/jre

# 端口号
PORTS=(7077 7078)
# 模块
MODULES=(api-1 api-2)
# 模块名称
MODULE_NAMES=(测试-1 测试-2)
# jar包数组
JARS=(xxx1.jar xxx2.jar)
# jar包路径
JAR_PATH='/data/test'
# 日志路径
LOG_PATH='/data/test/logs'
# 启动方法
start() {
  echo "----------启动服务----------"
  local MODULE=
  local MODULE_NAME=
  local JAR_NAME=
  local command="$1"
  local commandOk=0
  local count=0
  local okCount=0
  local port=0
  for((i=0;i<${#MODULES[@]};i++))
  do
    MODULE=${MODULES[$i]}
    MODULE_NAME=${MODULE_NAMES[$i]}
    JAR_NAME=${JARS[$i]}
    PORT=${PORTS[$i]}
    if [ "$command" == "all" ] || [ "$command" == "$MODULE" ];then
      commandOk=1
      count=0
      if [ ! -d $LOG_PATH ];then
        mkdir $LOG_PATH
      fi
      PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
      if [ -n "$PID" ];then
        echo "$MODULE---$MODULE_NAME:已经运行,PID=$PID"
      else
          #这行命令根据自己的需要更改
        cd $JAR_PATH && nohup $JRE_HOME/bin/java -Xms256m -Xmx512m -jar $JAR_NAME --spring.config.location=config/application.yml --server.port=$PORT >> $LOG_PATH/$MODULE.log 2>&1 &
        PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
        while [ -z "$PID" ]
        do
          if (($count == 10));then
            echo "$MODULE---$MODULE_NAME:$(expr $count \* 10)秒内未启动,请检查!"
            break
          fi
          count=$(($count+1))
          echo "$MODULE_NAME启动中..."
          sleep 10s
          PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
        done
        okCount=$(($okCount+1))
        echo "$MODULE---$MODULE_NAME:已经启动成功,PID=$PID"
      fi
    fi
  done
  if(($commandOk == 0));then
    echo "第二个参数输入错误"
  else
    echo "----本次共启动:$okCount个服务----"
  fi
}

# 停止方法
stop() {
  echo "----------停止服务----------"
  local MODULE=
  local MODULE_NAME=
  local JAR_NAME=
  local command="$1"
  local commandOk=0
  local okCount=0
  for((i=0;i<${#MODULES[@]};i++))
  do
    MODULE=${MODULES[$i]}
    MODULE_NAME=${MODULE_NAMES[$i]}
    JAR_NAME=${JARS[$i]}
    if [ "$command" = "all" ] || [ "$command" = "$MODULE" ];then
      commandOk=1
      PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
      if [ -n "$PID" ];then
        echo "$MODULE---$MODULE_NAME:准备结束,PID=$PID"
        kill -9 $PID
        PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
        while [ -n "$PID" ]
        do
          sleep 3s
          PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
        done
        echo "$MODULE---$MODULE_NAME:成功结束"
        okCount=$(($okCount+1))
      else
        echo "$MODULE---$MODULE_NAME:未运行"
      fi
    fi
  done
  if (($commandOk == 0));then
    echo "第二个参数输入错误"
  else
    echo "----本次共停止:$okCount个服务----"
  fi
}

# 检查运行状态
status(){
  echo "------检查服务运行状态------"
  local MODULE=
  local MODULE_NAME=
  local JAR_NAME=
  local command="$1"
  local commandOk=0
  local okCount=0
  for((i=0;i<${#MODULES[@]};i++))
  do
    MODULE=${MODULES[$i]}
    MODULE_NAME=${MODULE_NAMES[$i]}
    JAR_NAME=${JARS[$i]}
    if [ "$command" = "all" ] || [ "$command" = "$MODULE" ];then
      commandOk=1
      PID=`ps -ef |grep $(echo $JAR_NAME | awk -F/ '{print $NF}') | grep -v grep | awk '{print $2}'`
      if [ -n "$PID" ];then
        echo "$MODULE---$MODULE_NAME:正在运行,PID=$PID"
        okCount=$(($okCount+1))
      else
        echo "$MODULE---$MODULE_NAME:未运行"
      fi
    fi
  done
  if (($commandOk == 0));then
    echo "第二个参数输入错误"
  else
    echo "------正在运行:$okCount个服务------"
  fi
}
 
# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
  start)
    start "$2"
  ;;
  stop)
    stop "$2"
  ;;
  status)
    status "$2"
  ;;
  restart)
    stop "$2"
    sleep 3s
    start "$2"
  ;;
  *)
    echo "sh startAll.sh [start|stop|restart|status] [all|模块名]"
    exit 1
  ;;
esac
exit 0

输入脚本文件内容后,按esc退出编辑模式,输入:wq保存退出,脚本就做好了

给脚本可执行权限

chmod a+x startAll.sh
给了权限就可以运行脚本来批量的管理api服务了

# 启动所有jar包
./startAll.sh start all
# 停止所有jar包
./startAll.sh stop all
# 重启所有jar包
./startAll.sh restart all
# 查看所有服务状态
./startAll.sh status all
# 如果需要操作单个jar包,只需要将all替换为需要操作的模块名而已

脚本操作演示
到此,批量管理api就完成了,可是既然都批量管理了,为何不一步到位开机自动启动呢?

设置脚本的开启自动启动

批量管理的脚本已经做好了,接下来可以制作一个系统服务,用来通过systemctl直接操作脚本
还可以直接添加开机启动,该操作只在CentOS7下测试通过,CentOS6可能有点不太一样

经过查询相关资料,CentOS7的systemctl脚本文件储存在/usr/lib/systemd/目录下
有系统(system)和用户(user)之分,其中系统服务为开机后不需要用户登录就可以运行的服务
所以我们将脚本存放在系统目录下,即 /usr/lib/systemd/system

创建systemctl脚本

使用vim创建脚本,文件后缀为.service
vi /usr/lib/systemd/system/myapis.service
参考以下代码来编写内容

[Unit]
#服务描述
Description=fanfan's api service
#在以下服务之后启动
After=syslog.target network.target

[Service]
#服务运行模式:后台模式
Type=forking
#启动服务时执行的命令
ExecStart=/data/api/domain/startAll.sh start all
#停止服务时执行的命令
ExecStop=/data/api/domain/startAll.sh stop all
#重启服务时执行的命令
ExecReload=/data/api/domain/startAll.sh restart all
#表示给服务分配独立的临时空间
PrivateTmp=True
#服务运行的用户和用户组
User=root
Group=root
#非正常退出时,自动重启,用作守护进程
Restart=on-failure

[Install]
#依赖配置
WantedBy=multi-user.target

编写好脚本文件后,按esc退出编辑模式,输入:wq保存退出,系统服务就做好了

添加可执行权限
chmod a+x /usr/lib/systemd/system/myapis.service

重载系统服务以使脚本生效
systemctl daemon-reload

先查看状态,显示load即脚本正常载入
systemctl status myapis
脚本载入示意.png

可使用一下命令来进行批量操作

# 启动服务
systemctl start myapis
# 关闭服务
systemctl stop myapis
# 重启服务
systemctl restart myapis
# 查看服务状态
systemctl status myapis

将服务添加开机自动启动

# 添加开机自启
systemctl enable tomcat.service
# 关闭开机自启
systemctl disable tomcat.service

若执行命令提示 Access denied

解决方案有两种:
1 systemctl daemon-reexec
2 setenforce 0

这样就可以直接使用systemctl命令来批量管理api服务了,并且实现了开机自动启动 吐舌.png


shell脚本参考了zns:https://www.cnblogs.com/zengnansheng/p/11380009.html