Напишите повторно используемый сценарий работы и обслуживания приложения SpringBoot.

задняя часть

помещение

в видеJavaРазработчик, будет использоваться во многих сценарияхSpringBootразвиватьWebПриложение, текущий мейнстрим микросервисовSpringCloudВсе семейное ведро также основано наSpringBootпостроен.SpringBootКогда приложение развертывается на сервере, необходимо написать сценарий управления эксплуатацией и обслуживанием. В этой статье делается попытка обобщить предыдущее производственное использование на основе опыта.Shellскрипт, напишите многоразовыйSpringBootПрименяйте сценарии эксплуатации и обслуживания, что значительно снижаетSpringBootРабочая нагрузка запуска приложения, состояния, перезапуска и т. д. управления. этой статьиShellсценарий вCentOS7Он нормально работает в других операционных системах и может не подходить для других операционных систем. Если вас не интересуют какие-то основы или принципы, вы можете перетащить его в конец и напрямую скопировать сценарий для использования.

Зависимые знания, связанные с Shell

написатьSpringBootСкрипты работы и обслуживания приложения в дополнение к базовымShellПомимо относительного владения грамматикой, необходимо решить еще две важные проблемы (по моему личному мнению):

  • Правильно получить процесс целевого приложенияID, то есть получитьProcess ID(именуемый в дальнейшемPID)Проблема.
  • killПравильное использование команд.
  • Заказnohupправильный способ его использования.

получить PID

В общем, если имя приложения может быть успешно полученоPID, можно определить, что процесс приложения запущен, в противном случае процесс приложения не выполняется. Состояние выполнения процесса приложения основано наPIDЭто оценивается, поэтому приобретение будет вызываться несколько раз в сценарии управления процессом приложения.PIDКоманда. обычно используютgrepкоманда найтиPID, например, следующая команда является запросомRedisУслугиPID:

ps -ef |grep redis |grep -v grep |awk '{print $2}'

На самом деле это составная команда, каждая|Далее следует полная автономная команда, где:

  • ps -efдаpsкоманда плюс-efпараметр,psКоманда в основном используется для просмотра соответствующего статуса процесса,-eозначает показать все процессы, а-fПредставляет полный вывод, чтобы показать отношения родитель-потомок между процессами, например, следующее находится на виртуальной машине автора.CentOS 7воплощать в жизньps -efРезультат после:

  • grep XXXНа самом деле этоgrepСоответствующий целевой параметр используется для поиска результата параметра целевого параметра, и Compeat Command будет искать с результата предыдущей команды.
  • grep -v grepэтоgrepИгнорируется при выполнении командыgrepсобственный процесс.
  • awk '{print $2}'Это вынуть второй столбец результата обработки.

ps -ef |grep redis |grep -v grep |awk '{print $2}'Процесс выполнения составной команды:

  • <1>пройти черезps -efПолучить статус системного процесса.
  • <2>пройти черезgrep redisот<1>результаты поиска вredisключевые слова, в результате чегоredisОбрабатывать информацию.
  • <3>пройти черезgrep -v grepот<2>Отфильтровать результаты вgrepсобственный процесс.
  • <4>пройти черезawk '{print $2}'от<3>Результат получает второй столбец.

существуетShellВ скрипте вы можете использовать этот метод для полученияPID:

PID=`ps -ef |grep redis-server |grep -v grep |awk '{print $2}'`
echo $PID

Но с этим будет проблема, то есть каждый раз, когда вы захотите получитьPIDНемного неудобно использовать эту очень длинную строку команд. можно использоватьevalУпростите процесс:

PID_CMD="ps -ef |grep docker |grep -v grep |awk '{print \$2}'"
PID=$(eval $PID_CMD)
echo $PID

ПолучатьPIDрешение проблемы, которое затем может быть основано наPIDНезависимо от того, существует он или нет, решите, что делать дальше.

Понять команду kill

killОбщая форма командыkill -N PID, основная функция состоит в том, чтобы соответствоватьPIDПроцесс отправки сигнала, а затем соответствующий процесс должен ответить на сигнал, номер сигналаN,этоNНеобязательные значения следующие (системаCentOS 7):

Наиболее распространен среди разработчиков9) SIGKILLи15) SIGTERM, а их общее описание выглядит следующим образом:

Номер сигнала Название сигнала описывать Функции Оказать влияние
15 SIGTERM Termination (ANSI) Система отправляетSIGTERMСигнал Процесс останавливается немедленно, или останавливается после освобождения ресурсов, или из-за ожиданияIOПродолжать находиться в запущенном состоянии, то есть вообще будет блокирующий процесс, или другими словами процесс может блокировать, обрабатывать или игнорироватьSIGTERMСигнал
9 SIGKILL Kill(can't be caught or ignored) (POSIX) Система отправляетSIGKILLСигнал SIGKILLСигналы нельзя игнорировать, обычно процесс сразу останавливается (конечно есть дополнительные случаи)

Без-NпараметрическийkillКоманда по умолчаниюkill -15. Вообще говоря,kill -9 PIDЭто обязательный метод завершения процесса, но он может повлиять на процесс высвобождения ресурсов или прервать процесс до его завершения.I/OОперация вызывает такие проблемы, как аномалии данных.

NOHUPCOMMAND

Если вы хотите, чтобы процесс приложения не завершался после выхода из учетной записи или закрытия терминала, вы можете использоватьnohupкоманда для запуска соответствующего процесса.

nohup — это аббревиатура от no hang up, что переводится как «не зависать».Функция nohup — выполнять команды без зависаний.

nohupФормат команды следующий:nohup Command [Arg...] [&]Функция: на основе командыCommandИ необязательные дополнительные параметрыArgвыполнить команду, игнорируя всеkillсигнал отбоя в командеSIGHUP,&Символ указывает на то, что команда должна выполняться в фоновом режиме.

Обратите внимание, что в операционной системе есть три широко используемых стандартных потока: 0: стандартный входной поток STDIN 1: стандартный выходной поток STDOUT 2: Стандартный поток ошибок STDERR

бежать напрямуюnohup Command &, все потоки стандартного вывода и вывода ошибок будут выводиться в текущий каталогnohup.outфайл, он может занимать много места на диске в течение длительного времени, поэтому обычно необходимо преобразовать стандартный поток выводаSTDOUTи стандартный поток ошибокSTDERRперенаправить на другие файлы, например.nohup Command 1>server.log 2>server.log &. Но из-за стандартного потока ошибокSTDERRБуферов нет, поэтому это приведет кserver.logБудет открываться дважды, вызывая содержание стандартных выходов и вывода ошибок, чтобы конкурировать и перезаписать друг друга, поэтому стандартный поток ошибок обычноSTDERRперенаправить на уже открытый стандартный поток выводаSTDOUT, что часто можно увидеть2>&1, а стандартный поток выводаSTDOUTможно опустить>фронт1,так:

Команда nohup 1> server.log 2> server.log и изменить Команда nohup> server.log 2> & 1 &

Однако чащеJavaПри подаче заявки приложение будет специально печатать лог в определенную директорию на диске для удобства.ELKКоллекция, например, правила эксплуатации и обслуживания бывшей компании автора, журнал должен быть напечатан в/data/log-center/${serverName}каталог, то вы должны поместитьnohupстандартный поток выводаSTDOUTи стандартный поток ошибокSTDERRполностью игнорируется. Более реальный подход — перенаправить все эти два стандартных потока в «черную дыру»./dev/null"В. Например:

nohup Command >/dev/null 2>&1 &

Написание сценариев работы и обслуживания приложения SpringBoot.

SpringBootПриложение по сути являетсяJavaприложения, но можно добавить конкретныеSpringBootРазрешенные параметры, ниже будет пошагово проанализировано, как написать многоразовый сценарий работы и обслуживания.

глобальная переменная

Рассмотрение возможного повторного использования переменных и повышение простоты скрипта, где можно повторно использовать первые извлекаемые глобальные переменные. Во-первых, определениеJDKпозицияJDK_HOME:

JDK_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/bin/java"

Затем определите местоположение приложенияAPP_LOCATION:

APP_LOCATION="/data/shell/app.jar"

Затем определите имя приложенияAPP_NAME(в основном используется для поиска и отображения):

APP_NAME="app"

Затем определите получитьPIDвременная переменная командыPID_CMD, используемый для получения позжеPIDВременная переменная:

PID_CMD="ps -ef |grep $APP_LOCATION |grep -v grep |awk '{print \$2}'"
// PID = $(eval $PID_CMD)

Определить свойства виртуальной машиныVM_OPTS:

VM_OPTS="-Xms2048m -Xmx2048m"

определениеSpringBootАтрибутыSPB_OPTS(Обычно используется для настройки порта запуска, приложенияProfileили адрес регистрации и т. д.):

SPB_OPTS="--spring.profiles.active=dev"

В основном это параметры, которые можно изменить или добавить в соответствии с реальной сценой.

Напишите основной метод

Например, файл сценарияserver.sh, Вам нужно использовать окончательныйsh server.sh Commandвыполнить, чтоCommandСписок выглядит следующим образом:

  • start: Запустить службу.
  • info: Печать информации, в основном содержимого общих переменных.
  • status: распечатать статус службы, который используется для определения того, запущена ли служба.
  • stop: остановить процесс обслуживания.
  • restart: Перезапустите службу.
  • help: Справочная руководство.

здесь черезcaseКлючевое слово и первый параметр, введенный при выполнении команды, определяют конкретный метод вызова.

start() {
 echo "start: start server"
}

stop() {
 echo "stop: shutdown server"
}

restart() {
 echo "restart: restart server"
}

status() {
 echo "status: display status of server"
}

info() {
 echo "help: help info"
}

help() {
   echo "start: start server"
   echo "stop: shutdown server"
   echo "restart: restart server"
   echo "status: display status of server"
   echo "info: display info of server"
   echo "help: help info"
}

case $1 in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status
    ;;
info)
    info
    ;;
help)
    help
    ;;
*)
    help
    ;;
esac
exit $?

есть тест:

[root@localhost shell]# sh server.sh 
start: start server
stop: shutdown server
restart: restart server
status: display status of server
info: display info of server
help: help info
......
[root@localhost shell]# sh c.sh start
start: start server

Затем нужно написать соответствующую реализацию метода.

информационный метод

info()Он в основном используется для печати переменных среды текущей службы, информации о службе и т. д.

info() {
  echo "=============================info=============================="
  echo "APP_LOCATION: $APP_LOCATION"
  echo "APP_NAME: $APP_NAME"
  echo "JDK_HOME: $JDK_HOME"
  echo "VM_OPTS: $VM_OPTS"
  echo "SPB_OPTS: $SPB_OPTS"
  echo "=============================info=============================="
}

метод статуса

status()Этот метод в основном используется для отображения текущего состояния службы.

status() {
  echo "=============================status==============================" 
  PID=$(eval $PID_CMD)
  if [[ -n $PID ]]; then
       echo "$APP_NAME is running,PID is $PID"
  else
       echo "$APP_NAME is not running!!!"
  fi
  echo "=============================status=============================="
}

метод запуска

start()Этот метод в основном используется для запуска службы и должен использоватьсяJDKиnohupи другие сопутствующие команды.

start() {
 echo "=============================start=============================="
 PID=$(eval $PID_CMD)
 if [[ -n $PID ]]; then
    echo "$APP_NAME is already running,PID is $PID"
 else
    nohup $JDK_HOME $VM_OPTS -jar $APP_LOCATION $SPB_OPTS >/dev/null 2>\$1 &
    echo "nohup $JDK_HOME $VM_OPTS -jar $APP_LOCATION $SPB_OPTS >/dev/null 2>\$1 &"
    PID=$(eval $PID_CMD)
    if [[ -n $PID ]]; then
       echo "Start $APP_NAME successfully,PID is $PID"
    else
       echo "Failed to start $APP_NAME !!!"
    fi
 fi  
 echo "=============================start=============================="
}
  • Сначала определите, запущено ли уже приложение, если процесс приложения уже можно получитьPID, затем вернитесь напрямую.
  • использоватьnohupОбъединение командjava -jarкоманда для запуска приложенияjarпакет, основанный наPIDОпределите, был ли запуск успешным.

метод остановки

stop()метод используется для завершения процесса приложения, здесь для относительной безопасности и изяществаkillБросьте процесс, используйте сначалаkill -15кстати, конечноkill -15Не удалось убить процесс, затем используйтеkill -9.

stop() {
 echo "=============================stop=============================="
 PID=$(eval $PID_CMD)
 if [[ -n $PID ]]; then
    kill -15 $PID
    sleep 5
    PID=$(eval $PID_CMD)
    if [[ -n $PID ]]; then
      echo "Stop $APP_NAME failed by kill -15 $PID,begin to kill -9 $PID"
      kill -9 $PID
      sleep 2
      echo "Stop $APP_NAME successfully by kill -9 $PID"
    else 
      echo "Stop $APP_NAME successfully by kill -15 $PID"
    fi 
 else
    echo "$APP_NAME is not running!!!"
 fi
 echo "=============================stop=============================="
}

метод перезапуска

На самом деле сначалаstop(),Сноваstart().

restart() {
  echo "=============================restart=============================="
  stop
  start
  echo "=============================restart=============================="
}

контрольная работа

Автор взял за основуSpringBootЗависимость только импортируетсяspring-boot-starter-webПростейшая зависимость, хит одинJarСумкаapp.jarна виртуальной машине/data/shellдиректорию и загрузите скрипт одновременноserver.shприбыть/data/shellПод содержанием:

/data/shell
  - app.jar
  - server.sh

Результат теста следующий:

[root@localhost shell]# sh server.sh info
=============================info==============================
APP_LOCATION: /data/shell/app.jar
APP_NAME: app
JDK_HOME: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/bin/java
VM_OPTS: -Xms2048m -Xmx2048m
SPB_OPTS: --spring.profiles.active=dev
=============================info==============================
......
[root@localhost shell]# sh server.sh start
=============================start==============================
app is already running,PID is 26950
=============================start==============================
......
[root@localhost shell]# sh server.sh stop
=============================stop==============================
Stop app successfully by kill -15 
=============================stop==============================
......
[root@localhost shell]# sh server.sh restart
=============================restart==============================
=============================stop==============================
app is not running!!!
=============================stop==============================
=============================start==============================
Start app successfully,PID is 27559
=============================start==============================
=============================restart==============================
......
[root@localhost shell]# curl http://localhost:9091/ping -s
[root@localhost shell]# pong

Тестовый скрипт подтверждает правильность результата выполнения. один из них=================Это автор, который намеренно добавил его намеренно, если вы обнаружите его раздражающим, вы можете удалить его.

резюме

SpringBootв настоящее время или в течение длительного времени в будущемWebОсновной фреймворк в сервисе, автору потребовалось немного времени, чтобы изучитьShellсвязанный синтаксис в сочетании сnohup,psЖдатьLinuxКоманда написала повторно используемый сценарий работы и обслуживания приложения, который применялся в тестовой и производственной средах, что в определенной степени снижает затраты на эксплуатацию и обслуживание.

Использованная литература:

приложение

Нижеserver.shВсе содержимое скрипта:

#!/bin/bash
JDK_HOME="/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/bin/java"
VM_OPTS="-Xms2048m -Xmx2048m"
SPB_OPTS="--spring.profiles.active=dev"
APP_LOCATION="/data/shell/app.jar"
APP_NAME="app"
PID_CMD="ps -ef |grep $APP_NAME |grep -v grep |awk '{print \$2}'"

start() {
 echo "=============================start=============================="
 PID=$(eval $PID_CMD)
 if [[ -n $PID ]]; then
    echo "$APP_NAME is already running,PID is $PID"
 else
    nohup $JDK_HOME $VM_OPTS -jar $APP_LOCATION $SPB_OPTS >/dev/null 2>\$1 &
    echo "nohup $JDK_HOME $VM_OPTS -jar $APP_LOCATION $SPB_OPTS >/dev/null 2>\$1 &"
    PID=$(eval $PID_CMD)
    if [[ -n $PID ]]; then
       echo "Start $APP_NAME successfully,PID is $PID"
    else
       echo "Failed to start $APP_NAME !!!"
    fi
 fi  
 echo "=============================start=============================="
}

stop() {
 echo "=============================stop=============================="
 PID=$(eval $PID_CMD)
 if [[ -n $PID ]]; then
    kill -15 $PID
    sleep 5
    PID=$(eval $PID_CMD)
    if [[ -n $PID ]]; then
      echo "Stop $APP_NAME failed by kill -15 $PID,begin to kill -9 $PID"
      kill -9 $PID
      sleep 2
      echo "Stop $APP_NAME successfully by kill -9 $PID"
    else 
      echo "Stop $APP_NAME successfully by kill -15 $PID"
    fi 
 else
    echo "$APP_NAME is not running!!!"
 fi
 echo "=============================stop=============================="
}

restart() {
  echo "=============================restart=============================="
  stop
  start
  echo "=============================restart=============================="
}

status() {
  echo "=============================status==============================" 
  PID=$(eval $PID_CMD)
  if [[ -n $PID ]]; then
       echo "$APP_NAME is running,PID is $PID"
  else
       echo "$APP_NAME is not running!!!"
  fi
  echo "=============================status=============================="
}

info() {
  echo "=============================info=============================="
  echo "APP_LOCATION: $APP_LOCATION"
  echo "APP_NAME: $APP_NAME"
  echo "JDK_HOME: $JDK_HOME"
  echo "VM_OPTS: $VM_OPTS"
  echo "SPB_OPTS: $SPB_OPTS"
  echo "=============================info=============================="
}

help() {
   echo "start: start server"
   echo "stop: shutdown server"
   echo "restart: restart server"
   echo "status: display status of server"
   echo "info: display info of server"
   echo "help: help info"
}

case $1 in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    restart
    ;;
status)
    status
    ;;
info)
    info
    ;;
help)
    help
    ;;
*)
    help
    ;;
esac
exit $?

личный блог

Время от времени он обновляется, пишутся только оригинальные тексты, и он ориентирован на архитектуру и параллелизм.

(Конец этой статьи c-2-d e-a-2020-03-01)

Технический публичный аккаунт ("Throwable Digest"), который время от времени выкладывает оригинальные технические статьи автора (никогда не занимайтесь плагиатом и не перепечатывайте):