Aplicativo Spring Boot como um serviço

197

Como configurar bem o aplicativo Spring Boot empacotado como jar executável como um serviço no sistema linux? Essa abordagem é recomendada ou devo converter este aplicativo em guerra e instalar no Tomcat?

Atualmente, posso executar o aplicativo de inicialização Spring a partir da screensessão, o que é bom, mas requer inicialização manual após a reinicialização do servidor.

O que estou procurando é conselho / direção geral ou init.dscript de exemplo , se minha abordagem com o jar executável for adequada.

MariuszS
fonte
Para começar, sua distribuição usa upstart ou systemd?
yglodt

Respostas:

138

O seguinte funciona para o springboot 1.3 e superior:

Como serviço init.d

O jar executável possui os comandos normais de início, parada, reinicialização e status. Ele também configurará um arquivo PID no diretório / var / run usual e efetuará login no diretório / var / log usual por padrão.

Você só precisa vincular seu jar no /etc/init.d assim

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

OU

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

Depois disso, você pode fazer o habitual

/etc/init.d/myapp start

Em seguida, configure um link no nível de execução em que você deseja que o aplicativo inicie / pare na inicialização, se assim o desejar.


Como um serviço systemd

Para executar um aplicativo Spring Boot instalado em var / myapp, você pode adicionar o seguinte script em /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

Nota: caso você esteja usando este método, não se esqueça de tornar o arquivo jar executável (com chmod + x), caso contrário, ele falhará com o erro "Permissão negada".

Referência

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

Chade
fonte
1
Como a abordagem "JAR totalmente executável" funciona? Eu uso o CentOS 6.6. Eu adicionei <executable>true</executable>ao meu pom.xml, mas o arquivo JAR empacotado não executa (... ./myapp.jar ... cannot execute binary file.)
Abdull
5
Esta resposta funciona apenas para o Marco 1.3 atual, que ainda não foi lançado. As ramificações 1.1 e 1.2 precisarão verificar as outras respostas aqui.
voor
6
Vocês sabem como passar os argumentos da primavera, como -Dspring.profiles.active=prodesses serviços? Pergunta - stackoverflow.com/questions/31242291/…
nKognito
2
Não consigo parar o aplicativo de inicialização por mola. /etc/init.d stopnão está parando o aplicativo, está tentando iniciá-lo novamente.
Tintin
2
Se você deseja monitorar o processo e reiniciá-lo se ele morrer sem gravar os daemons do sistema, confira patrickgrimard.com/2014/06/06/…
ruX
112

A seguir, é a maneira mais fácil de instalar um aplicativo Java como serviço de sistema no Linux.

Vamos supor que você esteja usando systemd(o que qualquer distribuição moderna atualmente faz):

Primeiro, crie um arquivo de serviço /etc/systemd/systemnomeado, por exemplo, javaservice.servicecom este conteúdo:

[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

Em segundo lugar, notifique systemdo novo arquivo de serviço:

systemctl daemon-reload

e habilitá-lo, para que ele seja executado na inicialização:

systemctl enable javaservice.service

Eventualmente, você pode usar os seguintes comandos para iniciar / parar seu novo serviço:

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

Desde que você esteja usando systemd, esta é a maneira mais não invasiva e limpa de configurar um aplicativo Java como serviço do sistema.

O que eu mais gosto nessa solução é o fato de você não precisar instalar e configurar nenhum outro software. O envio systemdfaz todo o trabalho para você e seu serviço se comporta como qualquer outro serviço do sistema. Agora, uso-o na produção há um tempo, em diferentes distros, e funciona como você esperaria.

Outra vantagem é que, usando /usr/bin/java, você pode facilmente adicionar jvmparâmetros, como -Xmx256m.

Leia também a systemdparte da documentação oficial do Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

yglodt
fonte
Infelizmente o systemd não está disponível para Centos 6
MariuszS
como ele sabe como parar isso? Grava o pid e depois mata?
mist
2
Com o Spring Boot 1.3+, você pode gerar um arquivo de guerra totalmente executável; portanto, não é necessário o bit java -jar ..., basta usar o nome do arquivo.
Pierre Henry
1
Prefiro usar a linha de comando java completa, pois dessa forma você pode adicionar parâmetros jvm.
yglodt 17/08/19
1
Para uma seqüência de inicialização adequada, você pode querer adicionar declarações de ordenação à [Unit]seção, por exemplo After=mysql.service, Before=apache2.service.
rustyx 25/01
57

Você também pode usar o supervisord, que é um daemon muito útil, que pode ser usado para controlar facilmente os serviços. Esses serviços são definidos por arquivos de configuração simples que definem o que executar com qual usuário em qual diretório e assim por diante, há um zilhão de opções. O supervisord possui uma sintaxe muito simples, portanto, é uma alternativa muito boa para escrever scripts de inicialização do SysV.

Aqui está um arquivo de configuração de supervisão simples para o programa que você está tentando executar / controlar. (coloque isso em /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

Para controlar o aplicativo, você precisará executar o supervisorctl , que apresentará um prompt onde você pode iniciar, parar, status do seu pacote.

CLI

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

Se o supervisorddaemon já estiver em execução e você adicionou a configuração para seu serviço sem reiniciar o daemon, você pode simplesmente executar um comando rereade updateno supervisorctlshell.

Isso realmente oferece todas as flexibilidades que você teria usando os scripts SysV Init, mas fáceis de usar e controlar. Dê uma olhada na documentação .

flazzarini
fonte
Finalmente, algo funcionou para mim imediatamente. Muito obrigado pela dica supervisord.
Vitaly Sazanovich 27/11/19
Isso faz o mesmo trabalho que systemd, incorporado às distribuições Linux mais atuais.
rustyx 24/01
18

Eu mesmo acabei de fazer isso, então o seguinte é onde estou tão longe em termos de um script de controlador de serviço init.d do CentOS. Até agora, está funcionando muito bem, mas não sou um hacker da Bash, por isso tenho certeza de que há espaço para melhorias;

Primeiro de tudo, eu tenho um script de configuração curto /data/svcmgmt/conf/my-spring-boot-api.shpara cada serviço, que define variáveis ​​de ambiente.

#!/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

Estou usando o CentOS, portanto, para garantir que meus serviços sejam iniciados após a reinicialização do servidor, tenho um script de controle de serviço em /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

Como você pode ver, isso chama o script de configuração inicial para configurar variáveis ​​de ambiente e, em seguida, chama um script compartilhado que eu uso para reiniciar todos os meus serviços do Spring Boot. Esse script compartilhado é onde a carne de tudo isso pode ser encontrada:

#!/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

Ao parar, ele tentará usar o Spring Boot Actuator para executar um desligamento controlado. No entanto, se o Actuator não estiver configurado ou falhar ao desligar dentro de um período de tempo razoável (eu dou 5 segundos, o que é realmente um pouco curto), o processo será interrompido.

Além disso, o script pressupõe que o processo java que executa o aplicativo será o único com "my-spring-boot-api.jar" no texto dos detalhes do processo. Essa é uma suposição segura no meu ambiente e significa que não preciso acompanhar os PIDs.

Steve
fonte
3
Não há necessidade de escrever seu próprio script de início / parada. Isso é fornecido a partir do Spring Boot 1.3 ou superior. Consulte docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… para obter mais detalhes.
11136 gregturn
É bom saber que é uma opção, mas tudo o que faz é remover a necessidade de executar o uso java -jar. O restante do script ainda é necessário.
Steve
Muito útil para quando /etc/init.d ou systemd não é uma opção, obrigado por compartilhar.
bernardn
@ Steve: Não. Você está reinventando a roda. Ah, e nós temos systemd agora.
Martin Schröder
Quando você precisa passar parâmetros para a JVM (como os parâmetros -javaagent ou -D), essa é a maneira única, tks @Steve!
Dyorgio
14

Se você deseja usar o Spring Boot 1.2.5 com o Spring Boot Maven Plugin 1.3.0.M2, aqui está a solução:

<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>

Em seguida, compile como usual: mvn clean packagefaça um link simbólico ln -s /.../myapp.jar /etc/init.d/myapp, chmod +x /etc/init.d/myappexecute-o e inicie-o service myapp start(com o Ubuntu Server)

Benjamin M
fonte
e os arquivos WAR executáveis? isso não funciona para mim com o layout WAR.
Radu Toader
Curiosamente, isso funciona com o lançamento 1.3.0.M2, mas recebi um erro ao tentar 1.3.0.RC1.
JBCP #
Alguma idéia de como fazer isso com gradle em vez de maven?
Geir #
Ao usar o Gradle, essa configuração é feita usando o springBoot { executable = true }bloco.
Natix
@RaduToader: Você conseguiu executar o arquivo WAR como um serviço?
naveenkumarbv
9

Eu sei que essa é uma pergunta mais antiga, mas eu queria apresentar outra maneira, que é o appassembler-maven-plugin . Aqui está a parte relevante do meu POM que inclui muitos valores de opções adicionais que consideramos úteis:

<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>
voor
fonte
6

COMO UM SERVIÇO WINDOWS

Se você deseja que isso seja executado na máquina Windows, faça o download do winsw.exe em

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

Depois disso, renomeie-o para jar nome do arquivo (por exemplo: your-app .jar)

winsw.exe -> your-app.exe

Agora crie um arquivo xml your-app.xml e copie o seguinte conteúdo para esse

<?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>

Verifique se o exe e o xml junto com o jar estão na mesma pasta.

Após esse prompt de comando aberto, clique em Administrador e instale-o no serviço Windows.

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

Se falhar com

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

Em seguida, tente o seguinte:

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

é isso aí :) .

Para desinstalar o serviço no Windows

your-app.exe uninstall

Para ver / executar / parar o serviço: win + re digite Ferramentas administrativas e selecione o serviço a partir dele. Em seguida, clique com o botão direito do mouse e escolha a opção - executar / parar

Arundev
fonte
Segui as mesmas etapas para executar o jar de inicialização de primavera como serviço do Windows no ambiente da intranet da empresa, mas o serviço não está funcionando. Há uma janela saindo com erro: Erro: 1067 O processo foi encerrado inesperadamente. Você poderia ajudar ou sugerir o que precisa ser feito?
Nikhil Singh Bhadoriya 14/04
Você tem toda a permissão para fazer isso? Se você é um administrador, isso não causará nenhum problema. Você pode verificar se possui direitos de administrador.
Arundev 15/04
stackoverflow.com/questions/18205111/… você pode tentar isso? Isso pode ajudar a resolver o problema.
Arundev 15/04
obrigado pela resposta rápida, eu instalei meu serviço corrigindo um problema com a tag no arquivo xml.
Nikhil Singh Bhadoriya 15/04
4

Meu script SysVInit para Centos 6 / RHEL (ainda não é o ideal). Este script requer ApplicationPidListener .

Fonte de /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 $?

Arquivo de configuração de amostra /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
MariuszS
fonte
4

Aqui está um script que implanta um jar executável como um serviço systemd.

Ele cria um usuário para o serviço e o arquivo .service e coloca o arquivo jar em / var, além de bloquear alguns privilégios básicos.

#!/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

Exemplo: insira a descrição da imagem aqui

Usuário0
fonte
4

Estou tentando criar aplicativos springboot que são apresentados como um shell script no estilo "init.d", com um aplicativo java compactado na parte final

Ligando esses scripts de /etc/init.d/spring-app para /opt/spring-app.jar e chmod'ing o jar para ser executável, é possível iniciar "/etc/init.d/spring-app "/etc/init.d/spring-app stop" e outras possibilidades, como status de trabalho

Presumivelmente, como os scripts no estilo init.d do springboot parecem ter as seqüências mágicas necessárias (como # Default-Start: 2 3 4 5), o chkconfig poderia adicioná-lo como um "serviço"

Mas eu queria fazê-lo funcionar com o systemd

Para fazer esse trabalho, tentei muitos dos recebimentos nas outras respostas acima, mas nenhum deles funcionou para mim no Centos 7.2 com Springboot 1.3.

No final, descobri que o seguinte funcionou para mim, quando o link /etc/init.d também estava em vigor. Um arquivo semelhante ao abaixo deve ser instalado como/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
Vorsprung
fonte
4

Acabei fazendo o serviço systemd para o layout WAR / JAR

Estou chamando java -jar porque é mais flexível. Tentei também colocar o ExecStart = spring-mvc.war, mas mesmo sendo executável, recebi 'Exec format error'

De qualquer forma, atualmente, o systemd está presente em todas as distros e oferece uma boa solução para redirecionar logs (o syserr é importante quando o serviço nem inicia o local do arquivo log4j estará vazio :)).

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 - redireciona a entrada do syslog do aplicativo para uma pasta / arquivo específico

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
}

logrotate 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
}
Radu Toader
fonte
3

Nesta pergunta, a resposta de @PbxMan deve começar:

Executar um aplicativo Java como um serviço no Linux

Editar:

Existe outra maneira menos agradável de iniciar um processo na reinicialização, usando cron:

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

Isso funciona, mas não fornece uma interface agradável de iniciar / parar para o seu aplicativo. Você ainda pode simplesmente killassim mesmo ...

yglodt
fonte
Na verdade, não, porque o Spring Boot oferece recursos especiais para fazer isso.
Tristan
2

Eu não conheço uma maneira "padrão" simplificada de fazer isso com um aplicativo Java, mas é definitivamente uma boa idéia (você deseja se beneficiar dos recursos de manutenção e monitoramento do sistema operacional, se houver) . Está no roteiro fornecer algo do suporte da ferramenta Spring Boot (maven e gradle), mas por enquanto você provavelmente precisará rolar o seu próprio. A melhor solução que conheço agora é o Foreman , que possui uma abordagem declarativa e comandos de uma linha para empacotar scripts init para vários formatos padrão de SO (monit, sys V, upstart etc.). Também há evidências de pessoas configurando coisas com gradle (por exemplo, aqui ).

Dave Syer
fonte
2

Você está usando o Maven? Então você deve tentar o AppAssembler Plugin:

O plug-in Application Assembler é um plug-in Maven para gerar scripts para iniciar aplicativos java. ... Todos os artefatos (dependências + o artefato do projeto) são adicionados ao caminho de classe nos scripts de bin gerados.

Plataformas suportadas:

Variantes do Unix

Windows NT (Windows 9x NÃO é suportado)

JSW (Java Service Wrapper)

Veja: http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/index.html

d0x
fonte
2

A seguinte configuração é necessária no arquivo build.gradle nos projetos do Spring Boot.

build.gradle

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

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

executável = true

Isso é necessário para criar jar totalmente executável no sistema unix (Centos e Ubuntu)

Crie um arquivo .conf

Se você deseja configurar propriedades personalizadas da JVM ou argumentos de execução do aplicativo Spring Boot, é possível criar um arquivo .conf com o mesmo nome que o nome do aplicativo Spring Boot e colocá-lo paralelo ao arquivo jar.

Considerando que your-app.jar é o nome do seu aplicativo Spring Boot, você pode criar o seguinte arquivo.

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

Essa configuração definirá 64 MB de RAM para o aplicativo Spring Boot e ativará o perfil do produto.

Crie um novo usuário no linux

Para maior segurança, precisamos criar um usuário específico para executar o aplicativo Spring Boot como um serviço.

Crie um novo usuário

sudo useradd -s /sbin/nologin springboot

No Ubuntu / Debian, modifique o comando acima da seguinte maneira:

sudo useradd -s /usr/sbin/nologin springboot

Configurar senha

sudo passwd springboot

Tornar o springboot o proprietário do arquivo executável

chown springboot:springboot your-app.jar

Impedir a modificação do arquivo jar

chmod 500 your-app.jar

Isso configurará as permissões do jar para que ele não possa ser gravado e só possa ser lido ou executado por seu proprietário, springboot.

Opcionalmente, você pode tornar seu arquivo jar imutável usando o comando change attribute (chattr).

sudo chattr +i your-app.jar

Permissões apropriadas também devem ser definidas para o arquivo .conf correspondente. .conf requer apenas acesso de leitura (Octal 400) em vez de acesso de leitura + execução (Octal 500)

chmod 400 your-app.conf

Criar serviço 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

Reinicie o processo automaticamente se for morto pelo sistema operacional

Anexe os dois atributos abaixo (Reiniciar e RestartSec) para reiniciar automaticamente o processo em caso de falha.

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

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

A alteração fará com que o aplicativo Spring Boot seja reiniciado em caso de falha com um atraso de 30 segundos. Se você parar o serviço usando o comando systemctl, a reinicialização não ocorrerá.

Agendar serviço na inicialização do sistema

Para sinalizar o aplicativo para iniciar automaticamente na inicialização do sistema, use o seguinte comando:

Habilitar o aplicativo Spring Boot na inicialização do sistema

sudo systemctl enable your-app.service

Iniciar uma parada do serviço

O systemctl pode ser usado no Ubuntu 16.04 LTS e 18.04 LTS para iniciar e parar o processo.

Iniciar o processo

sudo systemctl start your-app

Pare o processo

sudo systemctl stop your-app

Referências

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

ismael
fonte
1

Seguindo a excelente resposta do Chade, se você receber um erro de "Erro: Não foi possível encontrar ou carregar a classe principal" - e você passar algumas horas tentando solucionar o problema, esteja executando um script de shell que inicia seu aplicativo java ou inicie-o do próprio systemd - e você sabe que seu caminho de classe está 100% correto, por exemplo, executar manualmente o shell script funciona bem como executar o que você possui no systemd execstart. Verifique se você está executando as coisas como o usuário correto! No meu caso, eu tentei usuários diferentes, depois de um tempo de solução de problemas - eu finalmente tive um palpite, coloquei root como usuário - pronto, o aplicativo foi iniciado corretamente. Depois de determinar que era um problema errado do usuário, euchown -R user:user a pasta e as subpastas e o aplicativo foram executados corretamente como o usuário e o grupo especificados, não sendo mais necessário executá-lo como raiz (segurança ruim).

JGlass
fonte
1

Nos arquivos da unidade systemd, você pode definir o diretório de variáveis ​​de ambiente ou através de um EnvironmentFile. Eu proporia fazer as coisas dessa maneira, pois parece ser a menor quantidade de atrito.

Arquivo de unidade de amostra

$ 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

Em seguida, configure um arquivo no /etc/sysconfig/hello-worldqual inclua nomes em maiúsculas de suas variáveis ​​do Spring Boot Por exemplo, uma variável chamada server.portseguiria o formulário SERVER_PORTcomo uma variável de ambiente:

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

O mecanismo que está sendo explorado aqui é que os aplicativos Spring Boot pegarão a lista de propriedades e as converterão, colocando tudo em maiúsculas e substituindo pontos por sublinhados. Depois que o aplicativo Spring Boot passa por esse processo, ele procura variáveis ​​de ambiente que correspondam e usa as encontradas de acordo.

Isso é destacado em mais detalhes nesta SO Q&A intitulada: Como definir uma propriedade Spring Boot com um sublinhado em seu nome por meio de variáveis ​​de ambiente?

Referências

slm
fonte
1

Isso pode ser feito usando o serviço Systemd no 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

Você pode seguir este link para obter uma descrição mais elaborada e diferentes maneiras de fazer isso. http://www.baeldung.com/spring-boot-app-as-a-service

mujeeb rahman
fonte
1

Crie um script com o nome your-app.service (rest-app.service). Devemos colocar esse script no diretório / etc / systemd / system. Aqui está o conteúdo de amostra do script

[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

Próximo:

 service rest-app start

Referências

insira a descrição do link aqui

ismael
fonte
Parece o mesmo assim -> stackoverflow.com/a/30497095/516167
MariuszS