Приложение Spring Boot как сервис


197

Как правильно настроить приложение Spring Boot, упакованное как исполняемый jar-файл как Сервис в системе Linux? Это рекомендуемый подход, или я должен преобразовать это приложение в войну и установить его в Tomcat?

В настоящее время я могу запустить загрузочное приложение Spring из screenсеанса, что неплохо, но требует перезагрузки вручную после перезагрузки сервера.

То, что я ищу, это общий совет / направление или пример init.dсценария, если мой подход с исполняемым jar является правильным.


Для начала, ваш дистрибутив использует upstart или systemd?
Иглодт

Ответы:


139

Следующие работы для Springboot 1.3 и выше:

В качестве службы init.d

Исполняемый файл jar содержит обычные команды start, stop, restart и status. Он также настроит PID-файл в обычном каталоге / var / run и войдет в обычный каталог / var / log по умолчанию.

Вам просто нужно добавить ссылку на ваш jar-файл в /etc/init.d примерно так

sudo link -s /var/myapp/myapp.jar /etc/init.d/myapp

ИЛИ

sudo ln -s ~/myproject/build/libs/myapp-1.0.jar /etc/init.d/myapp_servicename

После этого вы можете сделать обычное

/etc/init.d/myapp start

Затем установите ссылку в зависимости от того, какой уровень запуска вы хотите, чтобы приложение запускалось / останавливалось при загрузке, если это необходимо.


Как системный сервис

Чтобы запустить приложение Spring Boot, установленное в var / myapp, вы можете добавить следующий скрипт в /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

[Service]
ExecStart=/var/myapp/myapp.jar

[Install]
WantedBy=multi-user.target

Примечание: если вы используете этот метод, не забудьте сделать сам файл jar исполняемым (с помощью chmod + x), иначе он завершится с ошибкой «Отказано в доступе».

Ссылка

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/html/deployment-install.html#deployment-service


1
Как работает подход «полностью исполняемый JAR»? Я использую CentOS 6.6. Я добавил <executable>true</executable>к своему pom.xml, но упакованный файл JAR не выполняется (.... ./myapp.jar ... cannot execute binary file)
Abdull

5
Этот ответ работает только для текущего Milestone 1.3, который еще не выпущен. 1.1 и 1.2 ветви должны будут проверить другие ответы здесь.
пакет для

6
Ребята, вы знаете, как передать аргументы Spring, такие как -Dspring.profiles.active=prodэти услуги? Вопрос - stackoverflow.com/questions/31242291/…
nKognito

2
Я не могу остановить приложение весенней загрузки. /etc/init.d stopне останавливает приложение, оно пытается запустить его снова.
Тинтин

2
Если вы хотите отслеживать процесс и перезапускать его, если он умирает без записи системных демонов, загляните
ruX

112

Далее следует самый простой способ установить приложение Java в качестве системной службы в Linux.

Давайте предположим, что вы используете systemd(что делает любой современный дистрибутив):

Во-первых, создайте файл службы с /etc/systemd/systemименем, например, javaservice.serviceс таким содержанием:

[Unit]
Description=Java Service

[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/data 
ExecStart=/usr/bin/java -Xmx256m -jar application.jar --server.port=8081
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Во-вторых, уведомить systemdо новом файле сервиса:

systemctl daemon-reload

и включите его, чтобы он работал при загрузке:

systemctl enable javaservice.service

В конце концов, вы можете использовать следующие команды для запуска / остановки вашей новой службы:

systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice

При условии, что вы используете systemd, это самый ненавязчивый и чистый способ настроить приложение Java как системный сервис.

Что мне особенно нравится в этом решении, так это то, что вам не нужно устанавливать и настраивать любое другое программное обеспечение. Поставленный продукт systemdвыполняет всю работу за вас, а ваш сервис работает как любой другой системный сервис. Некоторое время я использую его в производстве, в разных дистрибутивах, и он просто работает, как и следовало ожидать.

Еще одним плюсом является то, что, используя /usr/bin/java, вы можете легко добавлять jvmпараметры, такие как -Xmx256m.

Также прочтите эту systemdчасть в официальной документации Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html.


К сожалению, systemd недоступен для Centos 6
MariuszS

откуда он знает как это остановить? Записывает пид, а потом убивает его?
туман

2
В Spring Boot 1.3+ вы можете сгенерировать полностью исполняемый файл war, поэтому нет необходимости в бите java -jar ..., просто используйте там имя файла.
Пьер Генри

1
Я предпочитаю использовать полную командную строку Java, потому что таким образом вы можете добавить параметры jvm.
yglodt

1
Для правильной последовательности загрузки вы можете добавить заявление заказа в [Unit]раздел, например After=mysql.service, Before=apache2.service.
rustyx

57

Вы также можете использовать supervisord - очень удобный демон, который можно использовать для простого управления сервисами. Эти сервисы определяются простыми конфигурационными файлами, определяющими, что выполнять с каким пользователем, в каком каталоге и т. Д. Существуют миллионы опций. supervisord очень простой синтаксис, поэтому он является очень хорошей альтернативой написанию сценариев инициализации SysV.

Вот простой файл конфигурации супервизора для программы, которую вы пытаетесь запустить / контролировать. (поместите это в /etc/supervisor/conf.d/yourapp.conf )

/etc/supervisor/conf.d/yourapp.conf

[program:yourapp]
command=/usr/bin/java -jar /path/to/application.jar
user=usertorun
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/var/log/yourapp-stdout.log
stderr_logfile=/var/log/yourapp-stderr.log

Для управления приложением вам необходимо выполнить supervisorctl , который предоставит вам подсказку, где вы можете запустить, остановить, состояние yourapp.

CLI

# sudo supervisorctl
yourapp             RUNNING   pid 123123, uptime 1 day, 15:00:00
supervisor> stop yourapp
supervisor> start yourapp

Если supervisordдемон уже запущен и вы добавили конфигурацию для своей службы без перезапуска демона, вы можете просто выполнить команду a rereadи updateвsupervisorctl оболочке.

Это действительно дает вам все гибкие возможности, которые вы имели бы при использовании сценариев SysV Init, но прост в использовании и управлении. Посмотрите на документацию .


Наконец-то у меня сработало прямо из коробки. Большое спасибо за подсказку руководителя.
Виталий Сазанович

Это делает ту же работу systemd, что и встроенная в большинство современных дистрибутивов Linux.
rustyx

18

Я только что занялся этим сам, поэтому ниже я дошел до сценария контроллера службы CentOS init.d. Пока он работает довольно хорошо, но я не хакер Bash, так что я уверен, что есть возможности для улучшений, так что мысли об улучшении приветствуются.

Прежде всего, у меня есть короткий конфигурационный скрипт /data/svcmgmt/conf/my-spring-boot-api.shдля каждого сервиса, который устанавливает переменные среды.

#!/bin/bash
export JAVA_HOME=/opt/jdk1.8.0_05/jre
export APP_HOME=/data/apps/my-spring-boot-api
export APP_NAME=my-spring-boot-api
export APP_PORT=40001

Я использую CentOS, поэтому, чтобы мои службы запускались после перезапуска сервера, у меня есть сценарий управления службами /etc/init.d/my-spring-boot-api:

#!/bin/bash
# description: my-spring-boot-api start stop restart
# processname: my-spring-boot-api
# chkconfig: 234 20 80

. /data/svcmgmt/conf/my-spring-boot-api.sh

/data/svcmgmt/bin/spring-boot-service.sh $1

exit 0

Как вы можете видеть, он вызывает сценарий начальной настройки для настройки переменных среды, а затем вызывает общий сценарий, который я использую для перезапуска всех моих служб Spring Boot. В этом общем сценарии можно найти суть всего этого:

#!/bin/bash

echo "Service [$APP_NAME] - [$1]"

echo "    JAVA_HOME=$JAVA_HOME"
echo "    APP_HOME=$APP_HOME"
echo "    APP_NAME=$APP_NAME"
echo "    APP_PORT=$APP_PORT"

function start {
    if pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is already running. Ignoring startup request."
        exit 1
    fi
    echo "Starting application..."
    nohup $JAVA_HOME/bin/java -jar $APP_HOME/$APP_NAME.jar \
        --spring.config.location=file:$APP_HOME/config/   \
        < /dev/null > $APP_HOME/logs/app.log 2>&1 &
}

function stop {
    if ! pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    then
        echo "Service [$APP_NAME] is not running. Ignoring shutdown request."
        exit 1
    fi

    # First, we will try to trigger a controlled shutdown using 
    # spring-boot-actuator
    curl -X POST http://localhost:$APP_PORT/shutdown < /dev/null > /dev/null 2>&1

    # Wait until the server process has shut down
    attempts=0
    while pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
    do
        attempts=$[$attempts + 1]
        if [ $attempts -gt 5 ]
        then
            # We have waited too long. Kill it.
            pkill -f $APP_NAME.jar > /dev/null 2>&1
        fi
        sleep 1s
    done
}

case $1 in
start)
    start
;;
stop)
    stop
;;
restart)
    stop
    start
;;
esac
exit 0

При остановке он попытается использовать Spring Boot Actuator для выполнения управляемого останова. Однако, если Actuator не настроен или не может отключиться в течение разумного периода времени (я даю ему 5 секунд, что на самом деле немного мало), процесс будет остановлен.

Кроме того, сценарий предполагает, что java-процесс, выполняющий приложение, будет единственным с «my-spring-boot-api.jar» в тексте деталей процесса. Это безопасное предположение в моей среде и означает, что мне не нужно отслеживать PID.


3
Нет необходимости писать свой собственный скрипт запуска / остановки. Это предоставляется начиная с версии Spring Boot 1.3 и выше. См. Docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… для получения более подробной информации.
gregturn

Приятно знать, что это вариант, но все, что он делает, это устраняет необходимость выполнения с помощью java -jar. Остальная часть сценария все еще нужна.
Стив

Очень полезно, когда /etc/init.d или systemd недоступны, спасибо, что поделились.
Бернардн

@ Стив: Нет. Вы заново изобретаете колесо. О, и теперь у нас есть systemd.
Мартин Шредер

Когда вам нужно передать параметры в JVM (например, параметры -javaagent или -D), это единственный способ, tks @Steve!
Диоргио

14

Если вы хотите использовать Spring Boot 1.2.5 с Spring Boot Maven Plugin 1.3.0.M2, вот вам решение:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.3.0.M2</version>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
    <pluginRepository>
        <id>spring-libs-milestones</id>
        <url>http://repo.spring.io/libs-milestone</url>
    </pluginRepository> 
</pluginRepositories>

Затем скомпилируйте как ususal:, mvn clean packageсоздайте символическую ссылку ln -s /.../myapp.jar /etc/init.d/myapp, сделайте ее исполняемой chmod +x /etc/init.d/myappи запустите ее service myapp start(с Ubuntu Server)


как насчет запускаемых файлов WAR? это не работает для меня с разметкой WAR.
Раду Toader

Интересно, что это работает с выпуском 1.3.0.M2, но я получил ошибку при попытке 1.3.0.RC1.
JBCP

Любая идея о том, как сделать это с Gradle вместо Maven?
Гейр

При использовании Gradle эта конфигурация выполняется с использованием springBoot { executable = true }блока.
Натикс

@RaduToader: Вам удалось выполнить WAR-файл как сервис?
naveenkumarbv

9

Я знаю, что это старый вопрос, но я хотел представить еще один способ - appassembler-maven-plugin . Вот соответствующая часть из моего POM, которая включает в себя множество дополнительных значений параметров, которые мы сочли полезными:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <configuration>
        <generateRepository>true</generateRepository>
        <repositoryLayout>flat</repositoryLayout>
        <useWildcardClassPath>true</useWildcardClassPath>
        <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
        <configurationDirectory>config</configurationDirectory>
        <target>${project.build.directory}</target>
        <daemons>
            <daemon>
                <id>${installer-target}</id>
                <mainClass>${mainClass}</mainClass>
                <commandLineArguments>
                    <commandLineArgument>--spring.profiles.active=dev</commandLineArgument>
                    <commandLineArgument>--logging.config=${rpmInstallLocation}/config/${installer-target}-logback.xml</commandLineArgument>
                </commandLineArguments>
                <platforms>
                    <platform>jsw</platform>
                </platforms>
                <generatorConfigurations>
                    <generatorConfiguration>
                        <generator>jsw</generator>
                        <includes>
                            <include>linux-x86-64</include>
                        </includes>
                        <configuration>
                            <property>
                                <name>wrapper.logfile</name>
                                <value>logs/${installer-target}-wrapper.log</value>
                            </property>
                            <property>
                                <name>wrapper.logfile.maxsize</name>
                                <value>5m</value>
                            </property>
                            <property>
                                <name>run.as.user.envvar</name>
                                <value>${serviceUser}</value>
                            </property>
                            <property>
                                <name>wrapper.on_exit.default</name>
                                <value>RESTART</value>
                            </property>
                        </configuration>
                    </generatorConfiguration>
                </generatorConfigurations>
                <jvmSettings>
                    <initialMemorySize>256M</initialMemorySize>
                    <maxMemorySize>1024M</maxMemorySize>
                    <extraArguments>
                        <extraArgument>-server</extraArgument>
                    </extraArguments>
                </jvmSettings>
            </daemon>
        </daemons>
    </configuration>
    <executions>
        <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
                <goal>generate-daemons</goal>
            </goals>
        </execution>
    </executions>
</plugin>

6

КАК WINDOWS СЕРВИС

Если вы хотите, чтобы это работало в машине Windows, загрузите winsw.exe из

 http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.1.2/

После этого переименуйте его в jar filename (например: your-app .jar)

winsw.exe -> your-app.exe

Теперь создайте xml-файл your-app.xml и скопируйте в него следующее содержимое.

<?xml version="1.0" encoding="UTF-8"?>
<service>
     <id>your-app</id>
     <name>your-app</name>
     <description>your-app as a Windows Service</description>
     <executable>java</executable>
     <arguments>-jar "your-app.jar"</arguments>
     <logmode>rotate</logmode>
</service>

Убедитесь, что exe и xml вместе с jar в одной папке.

После этого откройте командную строку в администраторе и установите ее в службу Windows.

your-app.exe install
eg -> D:\Springboot\your-app.exe install

Если это не с

Error: Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' has value '1.8', but '1.7' is required.

Затем попробуйте следующее:

Delete java.exe, javaw.exe and javaws.exe from C:\Windows\System32

Это оно :) .

Чтобы удалить службу в Windows

your-app.exe uninstall

Для просмотра / запуска / остановки службы: win + r и введите Администрирование, затем выберите службу из этого. Затем щелкните правой кнопкой мыши, выберите опцию - запустить / остановить


Я выполнил те же шаги, чтобы запустить весеннюю загрузку jar-файла как службу windows в корпоративной среде env, но служба не запускается. Появляется окно с ошибкой: Ошибка: 1067 Процесс неожиданно завершился. Не могли бы вы помочь или предложить, что нужно сделать?
Нихил Сингх Бхадория

У вас есть разрешение на это? Если вы являетесь администратором, это не вызовет никаких проблем. Можете ли вы проверить, есть ли у вас права администратора.
Арундев

stackoverflow.com/questions/18205111/… можете ли вы попробовать это, может быть, это поможет вам решить проблему.
Арундев

спасибо за быстрый ответ, я запустил службу, исправив проблему с тегом в xml-файле.
Никхил Сингх Бхадория

4

Мой скрипт SysVInit для Centos 6 / RHEL (пока не идеально). Этот скрипт требует ApplicationPidListener .

Источник /etc/init.d/app

#!/bin/sh
#
# app Spring Boot Application 
#
# chkconfig:   345 20 80
# description: App Service
#           

### BEGIN INIT INFO
# Provides: App
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 3 4 5 
# Default-Stop: 0 1 2 6
# Short-Description: Application
# Description:      
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

exec="/usr/bin/java"
prog="app"
app_home=/home/$prog/
user=$prog

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/$prog    
pid=$app_home/$prog.pid

start() {

    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    # Check that networking is up.
    [ "$NETWORKING" = "no" ] && exit 1
    echo -n $"Starting $prog: "
    cd $app_home
    daemon --check $prog --pidfile $pid --user $user $exec $app_args &
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc -p $pid $prog
    retval=$?
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    restart
}

force_reload() {
    restart
}

rh_status() {
    status -p $pid $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
exit $?

Пример файла конфигурации /etc/sysconfig/app:

exec=/opt/jdk1.8.0_05/jre/bin/java

user=myuser
app_home=/home/mysuer/

app_args="-jar app.jar"

pid=$app_home/app.pid

4

Вот скрипт, который развертывает исполняемый файл jar в качестве службы systemd.

Он создает пользователя для службы и файла .service и помещает файл jar в / var, а также выполняет базовую блокировку привилегий.

#!/bin/bash

# Argument: The jar file to deploy
APPSRCPATH=$1

# Argument: application name, no spaces please, used as folder name under /var
APPNAME=$2

# Argument: the user to use when running the application, may exist, created if not exists
APPUSER=$3

# Help text
USAGE="
Usage: sudo $0 <jar-file> <app-name> <runtime-user>
If an app with the name <app-name> already exist, it is stopped and deleted.
If the <runtime-user> does not already exist, it is created.
"

# Check that we are root
if [ ! "root" = "$(whoami)" ]; then
    echo "Must be root. Please use e.g. sudo"
    echo "$USAGE"
    exit
fi

# Check arguments
if [ "$#" -ne 3 -o ${#APPSRCPATH} = 0 -o ${#APPNAME} = 0 -o ${#APPUSER} = 0 ]; then
    echo "Incorrect number of parameters."
    echo "$USAGE"
    exit
fi

if [ ! -f $APPSRCPATH ]; then
    echo "Can't find jar file $APPSRCPATH"
    echo "$USAGE"
    exit
fi

# Infered values
APPFILENAME=$(basename $APPSRCPATH)
APPFOLDER=/var/javaapps/$APPNAME
APPDESTPATH=$APPFOLDER/$APPFILENAME

# Stop the service if it already exist and is running
systemctl stop $APPNAME >/dev/null 2>&1

# Create the app folder, deleting any previous content
rm -fr $APPFOLDER
mkdir -p $APPFOLDER

# Create the user if it does not exist
if id "$APPUSER" >/dev/null 2>&1; then
    echo "Using existing user $APPUSER"
else
    adduser --disabled-password --gecos "" $APPUSER
    echo "Created user $APPUSER"
fi

# Place app in app folder, setting owner and rights
cp $APPSRCPATH $APPDESTPATH
chown $APPUSER $APPDESTPATH
chmod 500 $APPDESTPATH
echo "Added or updated the $APPDESTPATH file"

# Create the .service file used by systemd
echo "
[Unit]
Description=$APPNAME
After=syslog.target
[Service]
User=$APPUSER
ExecStart=/usr/bin/java -jar $APPDESTPATH
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/$APPNAME.service
echo "Created the /etc/systemd/system/$APPNAME.service file"

# Reload the daemon
systemctl daemon-reload

# Start the deployed app
systemctl start $APPNAME
systemctl status $APPNAME

Пример: введите описание изображения здесь


4

Я пытаюсь создать приложения Springboot, которые представлены в виде сценария оболочки в стиле «init.d» со сжатым Java-приложением, прикрепленным к концу.

Путем символической ссылки на эти сценарии из /etc/init.d/spring-app в /opt/spring-app.jar и chmod'ing jar, чтобы он был исполняемым, можно запустить "/etc/init.d/spring-app "/etc/init.d/spring-app stop" и другие возможности, такие как работа со статусом

Предположительно, поскольку скрипты стиля init.d из Springboot выглядят так, что они имеют необходимые магические строки (например, # Default-Start: 2 3 4 5 ), chkconfig сможет добавить его в качестве «службы»

Но я хотел заставить его работать с systemd

Чтобы заставить это работать, я попробовал многие из получателей в других ответах выше, но ни один из них не работал для меня на Centos 7.2 с Springboot 1.3. В основном они запускали службу, но не могли отслеживать pid

В конце концов я обнаружил, что следующее сработало для меня, когда была установлена ​​ссылка /etc/init.d. Файл, аналогичный приведенному ниже, должен быть установлен как/usr/lib/systemd/system/spring-app.service

[Unit]
Description=My loverly application
After=syslog.target 

[Service]
Type=forking
PIDFile=/var/run/spring-app/spring-app.pid
ExecStart=/etc/init.d/spring-app start
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

4

Я закончил тем, что делал обслуживание systemd для разметки WAR / JAR

Я называю java -jar, потому что он более гибкий. Попытался также положить ExecStart = spring-mvc.war, но, несмотря на то, что это исполняемый файл, я получил «Ошибка формата Exec»

В любом случае, systemd присутствует во всех дистрибутивах и предлагает отличное решение для перенаправления журналов (syserr важен, когда ваша служба даже не запускает, местоположение файла log4j будет пустым :)).

cat /etc/systemd/system/spring-mvc.service 
[Unit]
Description=Spring MVC Java Service

[Service]
User=spring-mvc
# The configuration file application.properties should be here:
WorkingDirectory=/usr/local/spring-mvc


# Run ExecStartPre with root-permissions
PermissionsStartOnly=true

ExecStartPre=-/bin/mkdir -p /var/log/spring-mvc


ExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc
ExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc



#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
ExecStart=/usr/bin/java \
        -Dlog4j.configurationFile=log4j2-spring.xml \
        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \
        -Dspring.profiles.active=dev \
        -Denvironment-type=dev \
        -XX:+UseConcMarkSweepGC \
        -XX:CMSInitiatingOccupancyFraction=80 \
        -XX:NewSize=756m \
        -XX:MetaspaceSize=256m \
        -Dsun.net.inetaddr.ttl=5 \
        -Xloggc:/var/log/spring-mvc/gc.log \
        -verbose:gc \
        -verbosegc \
        -XX:+DisableExplicitGC \
        -XX:+PrintGCDetails \
        -XX:+PrintGCDateStamps \
        -XX:+PreserveFramePointer \
        -XX:+StartAttachListener \
        -Xms1024m \
        -Xmx1024m \
        -XX:+HeapDumpOnOutOfMemoryError \
        -jar spring-mvc.war

SuccessExitStatus=143
StandardOutput=journal
StandardError=journal


KillSignal=SIGINT
TimeoutStopSec=20
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=10

LimitNOFILE=500000
LimitNPROC=500000

#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=
#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=¶

SyslogIdentifier=spring-mvc

[Install]
WantedBy=multi-user.target


# https://www.freedesktop.org/software/systemd/man/journalctl.html
#check logs --- journalctl -u spring-mvc -f -o cat

rsyslog - перенаправить ввод системного журнала из приложения в определенную папку / файл

cat /etc/rsyslog.d/30-spring-mvc.conf 
if $programname == 'spring-mvc' then /var/log/spring-mvc/spring-mvc.log
& stop

Logrotate

cat /etc/logrotate.d/spring-mvc.conf 
/var/log/spring-mvc/spring-mvc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

войти gc

cat /etc/logrotate.d/spring-mvc-gc.conf 
/var/log/spring-mvc/gc.log
{
    daily
    rotate 30
    maxage 30
    copytruncate
    missingok
    notifempty
    compress
    dateext
    dateformat _%Y-%m-%d_%H-%M
    delaycompress
    create 644 spring-mvc syslog
    su spring-mvc syslog
}

3

В этом вопросе ответ от @PbxMan должен помочь вам начать:

Запустите приложение Java как службу в Linux

Редактировать:

Есть другой, менее приятный способ запустить процесс при перезагрузке, используя cron:

@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar

Это работает, но не дает вам приятного интерфейса запуска / остановки для вашего приложения. Вы все еще можете просто killэто все равно ...


Не совсем, потому что Spring Boot предлагает специальные функции для этого.
Тристан

2

Я не знаю «стандартного» термоусадочного способа сделать это с помощью Java-приложения, но это определенно хорошая идея (вы хотите воспользоваться возможностями поддержки активности и мониторинга операционной системы, если они там есть) , В планах обеспечить что-то из поддержки инструментов Spring Boot (maven и gradle), но сейчас вам, вероятно, придется катиться самостоятельно. Лучшее решение, которое я знаю сейчас, - это Foreman , который имеет декларативный подход и однострочные команды для упаковки сценариев инициализации для различных стандартных форматов ОС (monit, sys V, upstart и т. Д.). Есть также свидетельства того, что люди настроили вещи с помощью gradle (например, здесь ).


2

Вы используете Maven? Тогда вы должны попробовать плагин AppAssembler:

Плагин Application Assembler - это плагин Maven для генерации скриптов для запуска Java-приложений. ... Все артефакты (зависимости + артефакт из проекта) добавляются в путь к классам в сгенерированных сценариях bin.

Поддерживаемые платформы:

Unix-варианты

Windows NT (Windows 9x НЕ поддерживается)

Java Service Wrapper (JSW)

Смотрите: http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/index.html


2

Следующая конфигурация требуется в файле build.gradle в проектах Spring Boot.

build.gradle

jar {
    baseName = 'your-app'
    version = version
}

springBoot {
    buildInfo()
    executable = true   
    mainClass = "com.shunya.App"
}

исполняемый = верно

Это необходимо для того, чтобы сделать полностью исполняемый jar в системе Unix (Centos и Ubuntu)

Создать файл .conf

Если вы хотите настроить пользовательские свойства JVM или аргументы запуска приложения Spring Boot, то вы можете создать файл .conf с тем же именем, что и имя приложения Spring Boot, и разместить его параллельно файлу jar.

Учитывая, что your-app.jar - это имя вашего приложения Spring Boot, вы можете создать следующий файл.

JAVA_OPTS="-Xms64m -Xmx64m"
RUN_ARGS=--spring.profiles.active=prod
LOG_FOLDER=/custom/log/folder

Эта конфигурация установит 64 МБ оперативной памяти для приложения Spring Boot и активирует профиль prod.

Создать нового пользователя в Linux

Для повышения безопасности мы должны создать конкретного пользователя для запуска приложения Spring Boot в качестве службы.

Создать нового пользователя

sudo useradd -s /sbin/nologin springboot

В Ubuntu / Debian измените приведенную выше команду следующим образом:

sudo useradd -s /usr/sbin/nologin springboot

Установка пароля

sudo passwd springboot

Сделать Springboot владельцем исполняемого файла

chown springboot:springboot your-app.jar

Предотвратить изменение файла JAR

chmod 500 your-app.jar

Это настроит права доступа jar так, что он не может быть записан и может быть прочитан или выполнен только его владельцем springboot.

При желании вы можете сделать свой JAR-файл неизменным, используя команду change attribute (chattr).

sudo chattr +i your-app.jar

Соответствующие разрешения должны быть установлены и для соответствующего файла .conf. .conf требует только доступа на чтение (Octal 400) вместо доступа на чтение + выполнение (Octal 500)

chmod 400 your-app.conf

Создать сервис Systemd

/etc/systemd/system/your-app.service

[Unit]
Description=Your app description
After=syslog.target

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Автоматический перезапуск процесса, если он убит ОС

Добавьте следующие два атрибута (Restart и RestartSec), чтобы автоматически перезапустить процесс при сбое.

/etc/systemd/system/your-app.service

[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30

Это изменение приведет к перезагрузке приложения Spring Boot в случае сбоя с задержкой в ​​30 секунд. Если вы остановите службу с помощью команды systemctl, перезапуск не произойдет.

Расписание обслуживания при запуске системы

Чтобы пометить приложение для автоматического запуска при загрузке системы, используйте следующую команду:

Включить приложение Spring Boot при запуске системы

sudo systemctl enable your-app.service

Начать Остановить Сервис

systemctl может использоваться в Ubuntu 16.04 LTS и 18.04 LTS для запуска и остановки процесса.

Начать процесс

sudo systemctl start your-app

Остановить процесс

sudo systemctl stop your-app

Ссылки

https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html


1

В ответ на превосходный ответ Чада, если вы получите сообщение об ошибке «Ошибка: не удалось найти или загрузить основной класс» - и вы потратите пару часов на его устранение, будь то выполнение сценария оболочки, запускающего ваше Java-приложение, или запуск его из самой systemd - и вы знаете, что ваш classpath верен на 100%, например, ручной запуск сценария оболочки работает так же, как и запуск того, что у вас есть в systemd execstart. Убедитесь, что вы работаете как правильный пользователь! В моем случае я пробовал разных пользователей, после долгого времени поиска и устранения неисправностей - у меня наконец-то появилась догадка, поставил root как пользователь - вуаля, приложение запустилось правильно. После определения, что это была неправильная проблема пользователя, яchown -R user:user папка и подпапки, а также приложение работали правильно как указанные пользователь и группа, поэтому больше не нужно запускать их как root (плохая защита)


1

В системных файлах systemd вы можете установить каталог переменных среды или через EnvironmentFile. Я бы предложил действовать таким образом, так как это кажется наименьшим трением.

Пример файла модуля

$ cat /etc/systemd/system/hello-world.service
[Unit]
Description=Hello World Service
After=systend-user-sessions.service

[Service]
EnvironmentFile=/etc/sysconfig/hello-world
Type=simple
ExecStart=/usr/bin/java ... hello-world.jar

Затем настройте файл, в /etc/sysconfig/hello-worldкоторый входят имена переменных Spring Boot в верхнем регистре. Например, вызываемая переменная server.portбудет SERVER_PORTиметь форму переменной окружения:

$ cat /etc/sysconfig/hello-world
SERVER_PORT=8081

Используемый здесь механизм заключается в том, что приложения Spring Boot возьмут список свойств, а затем переведут их, сделав все в верхнем регистре и заменив точки на подчеркивания. Как только приложение Spring Boot проходит через этот процесс, оно ищет переменные среды, которые соответствуют, и использует любые найденные соответственно.

Это выделено более подробно в этой статье вопросов и ответов под названием: Как установить свойство Spring Boot с подчеркиванием в его имени через переменные среды?

Ссылки


1

Это можно сделать с помощью сервиса Systemd в Ubuntu.

[Unit]
Description=A Spring Boot application
After=syslog.target

[Service]
User=baeldung
ExecStart=/path/to/your-app.jar SuccessExitStatus=143

[Install] 
WantedBy=multi-user.target

Вы можете перейти по этой ссылке для более подробного описания и различных способов сделать это. http://www.baeldung.com/spring-boot-app-as-a-service


1

Создайте скрипт с именем your-app.service (rest-app.service). Мы должны поместить этот скрипт в каталог / etc / systemd / system. Вот пример содержимого скрипта

[Unit]
Description=Spring Boot REST Application
After=syslog.target

[Service]
User=javadevjournal
ExecStart=/var/rest-app/restdemo.jar
SuccessExitStatus=200

[Install]
WantedBy=multi-user.target

Следующий:

 service rest-app start

Ссылки

введите описание ссылки здесь


Выглядит так же, как это -> stackoverflow.com/a/30497095/516167
MariuszS
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.