Applicazione Spring Boot come servizio


197

Come configurare correttamente l'applicazione Spring Boot impacchettata come jar eseguibile come servizio nel sistema linux? Si tratta di un approccio consigliato o devo convertire questa app in guerra e installarla in Tomcat?

Attualmente posso eseguire l'applicazione di avvio Spring dalla screensessione, che è bello, ma richiede l'avvio manuale dopo il riavvio del server.

Quello che sto cercando sono consigli / indicazioni generali o init.dscript di esempio , se il mio approccio con il vaso eseguibile è corretto.


Per iniziare, la tua distribuzione utilizza upstart o systemd?
yglodt,

Risposte:


138

Il seguente funziona per Springboot 1.3 e versioni successive:

Come servizio init.d

Il vaso eseguibile ha i soliti comandi di avvio, arresto, riavvio e stato. Configura anche un file PID nella solita directory / var / run e accede alla solita directory / var / log per impostazione predefinita.

Devi solo collegare in modo simbolico il tuo jar in /etc/init.d in questo modo

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

O

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

Dopodiché puoi fare il solito

/etc/init.d/myapp start

Quindi imposta un collegamento in qualsiasi runlevel che desideri avviare / arrestare all'avvio dell'app se lo desideri.


Come servizio di sistema

Per eseguire un'applicazione Spring Boot installata in var / myapp è possibile aggiungere il seguente script in /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

NB: se si utilizza questo metodo, non dimenticare di rendere eseguibile il file jar stesso (con chmod + x), altrimenti fallirà con l'errore "Autorizzazione negata".

Riferimento

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


1
Come funziona l'approccio "JAR completamente eseguibile"? Uso CentOS 6.6. Ho aggiunto <executable>true</executable>al mio pom.xml, ma il file JAR confezionato non esegue (... ./myapp.jar ... cannot execute binary file.)
Abdull

5
Questa risposta funziona solo per l'attuale 1.3 Milestone, che non è ancora stato rilasciato. Le filiali 1.1 e 1.2 dovranno controllare qui le altre risposte.
per il

6
Sai ragazzi come passare argomenti di primavera come -Dspring.profiles.active=proda questi servizi? Domanda - stackoverflow.com/questions/31242291/...
nKognito

2
Non riesco a interrompere l'applicazione di avvio a molla. /etc/init.d stopnon sta arrestando l'app, sta provando a riavviarla.
tintin

2
Se vuoi monitorare il processo e riavviarlo se muore senza scrivere i demoni di sistema, controlla patrickgrimard.com/2014/06/06/…
ruX,

112

Quello che segue è il modo più semplice per installare un'applicazione Java come servizio di sistema in Linux.

Supponiamo che tu stia utilizzando systemd(cosa che oggi fa qualsiasi distribuzione moderna):

In primo luogo, creare un file di servizio in /etc/systemd/systemad esempio denominato javaservice.servicecon questo contenuto:

[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

In secondo luogo, notificare systemdil nuovo file di servizio:

systemctl daemon-reload

e abilitarlo, quindi viene eseguito all'avvio:

systemctl enable javaservice.service

Alla fine, puoi utilizzare i seguenti comandi per avviare / interrompere il tuo nuovo servizio:

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

A condizione che tu stia utilizzando systemd, questo è il modo più non intrusivo e pulito per configurare un'applicazione Java come servizio di sistema.

Quello che mi piace soprattutto di questa soluzione è il fatto che non è necessario installare e configurare nessun altro software. La spedizione systemdfa tutto il lavoro per te e il tuo servizio si comporta come qualsiasi altro servizio di sistema. Lo uso in produzione da un po 'di tempo, su diverse distro, e funziona come ci si aspetterebbe.

Un altro vantaggio è che, utilizzando /usr/bin/java, è possibile aggiungere facilmente jvmparametri come -Xmx256m.

Leggi anche la systemdparte nella documentazione ufficiale di Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html


Sfortunatamente systemd non è disponibile per Centos 6
MariuszS,

come fa a fermarlo? Registra il pid e poi lo uccide?
nebbia

2
Con Spring Boot 1.3+ è possibile generare un file di guerra completamente eseguibile, quindi non è necessario il bit java -jar ... basta usare qui il nome del file.
Pierre Henry,

1
Preferisco usare l'intera riga di comando Java perché in questo modo è possibile aggiungere parametri jvm.
yglodt,

1
Per una corretta sequenza di avvio che si potrebbe desiderare di aggiungere dichiarazioni di ordinazione alla [Unit]sezione, ad esempio After=mysql.service, Before=apache2.service.
Rustyx,

57

Puoi anche usare supervisord che è un demone molto utile, che può essere usato per controllare facilmente i servizi. Questi servizi sono definiti da semplici file di configurazione che definiscono cosa eseguire con quale utente in quale directory e così via, ci sono milioni di opzioni. supervisord ha una sintassi molto semplice, quindi è un'ottima alternativa alla scrittura di script init SysV.

Qui un semplice file di configurazione supervisord per il programma che si sta tentando di eseguire / controllare. (inseriscilo in /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

Per controllare l'applicazione dovresti eseguire supervisorctl , che ti presenterà un prompt in cui potresti iniziare, arrestare, stato yourapp.

CLI

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

Se il supervisorddaemon è già in esecuzione ed è stato aggiunto alla configurazione per il serivce senza riavviare il demone si può semplicemente fare un rereade updatecomando nella supervisorctlshell.

Questo ti dà davvero tutte le flessibilità che avresti usando gli script SysV Init, ma facili da usare e controllare. Dai un'occhiata alla documentazione .


Finalmente qualcosa ha funzionato per me fin da subito. Grazie mille per il suggerimento supervisord.
Vitaly Sazanovich,

Questo fa lo stesso lavoro di systemd , che è integrato nella maggior parte delle distribuzioni Linux attuali.
Rustyx,

18

Sono appena arrivato a farlo da solo, quindi di seguito sono dove mi trovo finora in termini di uno script controller di servizio Cent.d init.d. Finora funziona abbastanza bene, ma non sono un pazzo hacker Bash, quindi sono sicuro che ci sia spazio per miglioramenti, quindi i pensieri su come migliorarlo sono i benvenuti.

Prima di tutto, ho un breve script di configurazione /data/svcmgmt/conf/my-spring-boot-api.shper ogni servizio, che imposta le variabili di 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

Sto usando CentOS, quindi per garantire che i miei servizi vengano avviati dopo il riavvio del server, ho uno script di controllo del servizio in /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

Come puoi vedere, questo chiama lo script di configurazione iniziale per impostare le variabili di ambiente e quindi chiama uno script condiviso che utilizzo per riavviare tutti i miei servizi Spring Boot. Quella sceneggiatura condivisa è dove si trova la carne di tutto:

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

Durante l'arresto, tenterà di utilizzare Spring Boot Actuator per eseguire un arresto controllato. Tuttavia, nel caso in cui Actuator non sia configurato o non si spenga entro un lasso di tempo ragionevole (gli do 5 secondi, che in realtà è un po 'breve), il processo verrà interrotto.

Inoltre, lo script presuppone che il processo java che esegue l'application sarà l'unico con "my-spring-boot-api.jar" nel testo dei dettagli del processo. Questo è un presupposto sicuro nel mio ambiente e significa che non ho bisogno di tenere traccia dei PID.


3
Non è necessario scrivere il tuo script di avvio / arresto. Questo è fornito a partire da Spring Boot 1.3 e versioni successive. Vedi docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… per maggiori dettagli.
gregturn,

Buono a sapersi che è un'opzione, ma tutto ciò che fa è rimuovere la necessità di eseguire utilizzando java -jar. Il resto della sceneggiatura è ancora necessario.
Steve,

Molto utile per quando /etc/init.d o systemd non è un'opzione, grazie per la condivisione.
bernardn,

@Steve: No. Stai reinventando la ruota. Oh, e ora abbiamo systemd.
Martin Schröder,

Quando devi passare i parametri a JVM (come i parametri -javaagent o -D) questo è il modo unico, tks @Steve!
Dyorgio,

14

Se vuoi usare Spring Boot 1.2.5 con Spring Boot Maven Plugin 1.3.0.M2, ecco la soluzione:

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

Quindi compilare come di consueto:, mvn clean packagecreare un collegamento simbolico ln -s /.../myapp.jar /etc/init.d/myapp, renderlo eseguibile chmod +x /etc/init.d/myappe avviarlo service myapp start(con Ubuntu Server)


che dire dei file WAR eseguibili? non funziona per me con layout WAR.
Radu Toader,

È interessante notare che questo funziona con il rilascio 1.3.0.M2, ma ho avuto un errore quando ho provato 1.3.0.RC1.
JBCP,

Qualche idea su come farlo con Gradle anziché Maven?
Geir,

Quando si utilizza Gradle, questa configurazione viene eseguita utilizzando il springBoot { executable = true }blocco.
Natix,

@RaduToader: sei stato in grado di eseguire il file WAR come servizio?
naveenkumarbv,

9

So che questa è una domanda più vecchia, ma volevo presentare ancora un altro modo che è il appassembler-maven-plugin . Ecco la parte rilevante del mio POM che include molti altri valori opzionali che abbiamo trovato utili:

<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

COME SERVIZIO WINDOWS

Se vuoi che questo avvenga nel computer Windows, scarica il file winsw.exe

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

Dopodiché, rinominalo in jar nomefile (es. Tua-app .jar)

winsw.exe -> your-app.exe

Ora crea un file xml your-app.xml e copia il seguente contenuto in quello

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

Assicurati che exe e xml insieme a jar in una stessa cartella.

Dopo questo prompt dei comandi aperto in previlege amministratore e installarlo sul servizio Windows.

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

Se fallisce con

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

Quindi prova quanto segue:

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

questo è tutto :) .

Per disinstallare il servizio in Windows

your-app.exe uninstall

Per vedere / eseguire / interrompere il servizio: win + re digita Strumenti di amministrazione, quindi seleziona il servizio da quello. Quindi fai clic con il pulsante destro del mouse scegli l' opzione - esegui / arresta


Ho seguito gli stessi passaggi per eseguire il vaso di avvio a molla del servizio Windows nell'intranet aziendale, ma il servizio non si sta alzando. Viene visualizzata una finestra con errore: Errore: 1067 Il processo è terminato in modo imprevisto Potresti aiutare o suggerire cosa è necessario fare?
Nikhil Singh Bhadoriya,

Hai tutto il permesso per farlo? Se sei un amministratore questo non causerà alcun problema. Puoi verificare di disporre dei diritti di amministratore.
Arundev,

stackoverflow.com/questions/18205111/… puoi provare questo potrebbe essere questo ti aiuterà a risolvere il problema.
Arundev,

grazie per la rapida risposta, ho reso operativo il mio servizio correggendo un problema con il tag nel file xml.
Nikhil Singh Bhadoriya il

4

Il mio script SysVInit per Centos 6 / RHEL (non ancora ideale). Questo script richiede ApplicationPidListener .

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

File di configurazione di esempio /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

Ecco uno script che distribuisce un vaso eseguibile come servizio systemd.

Crea un utente per il servizio e il file .service, posiziona il file jar in / var e crea alcuni blocchi di base dei privilegi.

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

Esempio: inserisci qui la descrizione dell'immagine


4

Sto cercando di creare applicazioni Springboot presentate come uno script shell in stile "init.d" con un'applicazione java compressa incollata alla fine

Collegando in modo simbolico questi script da /etc/init.d/spring-app a /opt/spring-app.jar e modificando il jar come eseguibile è possibile avviare "/etc/init.d/spring-app start "" /etc/init.d/spring-app stop "e altre possibilità come status status

Presumibilmente, poiché gli script in stile init.d di Springboot sembrano avere le stringhe magiche necessarie (come # Default-Start: 2 3 4 5) chkconfig sarebbe in grado di aggiungerlo come "servizio"

Ma volevo farlo funzionare con systemd

Per fare questo lavoro ho provato molti dei destinatari nelle altre risposte sopra, ma nessuno di loro ha funzionato per me su Centos 7.2 con Springboot 1.3 Principalmente avrebbero avviato il servizio ma non sarebbero stati in grado di tracciare il pid

Alla fine ho scoperto che il seguente funzionava per me, quando era presente anche il collegamento /etc/init.d. Un file simile a quello seguente dovrebbe essere installato come/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

Ho finito per fare il servizio systemd per il layout WAR / JAR

Chiamo java -jar perché è più flessibile. Ho provato anche a mettere ExecStart = spring-mvc.war ma anche se è eseguibile, ho ricevuto "Errore formato Exec"

Ad ogni modo in questi giorni, systemd è presente su tutte le distro e offre una buona soluzione per reindirizzare i log (syserr è importante quando il tuo servizio non avvia nemmeno la posizione del file log4j sarà vuota :)).

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 - reindirizza l'input syslog dall'app a cartella / file specifici

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
}

3

In questa domanda, la risposta di @PbxMan dovrebbe iniziare:

Esegui un'applicazione Java come servizio su Linux

Modificare:

Esiste un altro modo meno piacevole per avviare un processo al riavvio, usando cron:

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

Funziona, ma non offre un'interfaccia di avvio / arresto piacevole per la tua applicazione. Puoi comunque semplicemente semplicemente kill...


Non proprio, perché Spring Boot offre funzionalità speciali per farlo.
Tristan,

2

Non conosco un modo "standard" di restringimento per farlo con un'app Java, ma è sicuramente una buona idea (vuoi trarre vantaggio dalle capacità di mantenimento e monitoraggio del sistema operativo se sono lì) . È sulla tabella di marcia fornire qualcosa dal supporto dello strumento Spring Boot (maven e gradle), ma per ora probabilmente dovrai fare il tuo. La migliore soluzione che conosco in questo momento è Foreman , che ha un approccio dichiarativo e comandi a una riga per impacchettare gli script di init per vari formati di sistema operativo standard (monit, sys V, upstart ecc.). Ci sono anche prove di persone che hanno sistemato le cose con Gradle (ad esempio qui ).


2

Stai usando Maven? Quindi dovresti provare il plugin AppAssembler:

Il plug-in Application Assembler è un plug-in Maven per la generazione di script per l'avvio di applicazioni Java. ... Tutti gli artefatti (dipendenze + l'artefatto dal progetto) vengono aggiunti al percorso di classe negli script bin generati.

Piattaforme supportate:

Unix-varianti

Windows NT (Windows 9x NON è supportato)

Java Service Wrapper (JSW)

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


2

La seguente configurazione è richiesta nel file build.gradle nei progetti Spring Boot.

build.gradle

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

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

eseguibile = vero

Ciò è necessario per creare un vaso completamente eseguibile sul sistema unix (Centos e Ubuntu)

Crea un file .conf

Se si desidera configurare proprietà JVM personalizzate o argomenti di esecuzione dell'applicazione Spring Boot, è possibile creare un file .conf con lo stesso nome del nome dell'applicazione Spring Boot e posizionarlo parallelamente al file jar.

Considerando che your-app.jar è il nome dell'applicazione Spring Boot, è possibile creare il seguente file.

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

Questa configurazione imposterà 64 MB di RAM per l'applicazione Spring Boot e attiverà il profilo prod.

Crea un nuovo utente in linux

Per una maggiore sicurezza, è necessario creare un utente specifico per eseguire l'applicazione Spring Boot come servizio.

Crea un nuovo utente

sudo useradd -s /sbin/nologin springboot

Su Ubuntu / Debian, modifica il comando sopra come segue:

sudo useradd -s /usr/sbin/nologin springboot

Impostare la password

sudo passwd springboot

Rendi Springboot il proprietario del file eseguibile

chown springboot:springboot your-app.jar

Impedire la modifica del file jar

chmod 500 your-app.jar

Ciò configurerà le autorizzazioni del jar in modo che non possa essere scritto e possa essere letto o eseguito solo dal suo avvio di primavera proprietario.

Opzionalmente puoi rendere il tuo file jar come immutabile usando il comando change Attribute (chattr).

sudo chattr +i your-app.jar

È necessario impostare autorizzazioni appropriate anche per il file .conf corrispondente. .conf richiede solo l'accesso in lettura (Octal 400) anziché l'accesso in lettura + esecuzione (Octal 500)

chmod 400 your-app.conf

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

Riavvia automaticamente il processo se viene ucciso dal sistema operativo

Aggiungi i due attributi seguenti (Restart e RestartSec) per riavviare automaticamente il processo in caso di errore.

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

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

La modifica farà riavviare l'applicazione Spring Boot in caso di errore con un ritardo di 30 secondi. Se si interrompe il servizio utilizzando il comando systemctl, il riavvio non avverrà.

Pianifica il servizio all'avvio del sistema

Per contrassegnare l'applicazione per l'avvio automatico all'avvio del sistema, utilizzare il comando seguente:

Abilita l'applicazione Spring Boot all'avvio del sistema

sudo systemctl enable your-app.service

Avvia un arresto del servizio

systemctl può essere utilizzato in Ubuntu 16.04 LTS e 18.04 LTS per avviare e interrompere il processo.

Inizia il processo

sudo systemctl start your-app

Ferma il processo

sudo systemctl stop your-app

Riferimenti

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


1

Seguendo l'eccellente risposta di Chad, se viene visualizzato l'errore "Errore: Impossibile trovare o caricare la classe principale" - e trascorri un paio d'ore nel tentativo di risolverlo, indipendentemente dal fatto che tu stia eseguendo uno script della shell che avvia l'app java o avviandola dallo stesso systemd - e sai che il tuo percorso di classe è corretto al 100%, ad esempio l'esecuzione manuale dello script di shell funziona così come l'esecuzione di ciò che hai in systemd execstart. Assicurarsi che di gestire le cose come l'utente corretto! Nel mio caso, avevo provato diversi utenti, dopo un po 'di risoluzione dei problemi - finalmente ho avuto un sospetto, ho messo root come utente - voilà, l'app è stata avviata correttamente. Dopo aver determinato che si trattava di un problema utente errato, Ichown -R user:user la cartella, le sottocartelle e l'app siano state eseguite correttamente come utente e gruppo specificati, quindi non è più necessario eseguirle come root (protezione non valida).


1

Nei file di unità di sistema è possibile impostare la directory delle variabili di ambiente o tramite un EnvironmentFile. Proporrei di fare le cose in questo modo poiché sembra essere la minima quantità di attrito.

File di unità di esempio

$ 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

Quindi imposta un file in /etc/sysconfig/hello-worldcui siano inclusi i nomi maiuscoli delle variabili Spring Boot. Ad esempio, una variabile chiamata server.portseguirebbe il modulo SERVER_PORTcome variabile d'ambiente:

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

Il meccanismo che viene sfruttato qui è che le applicazioni Spring Boot prenderanno l'elenco delle proprietà e poi le tradurranno, rendendo tutto maiuscolo e sostituendo i punti con caratteri di sottolineatura. Una volta che l'app Spring Boot ha completato questo processo, cerca le variabili di ambiente corrispondenti e utilizza quelle trovate di conseguenza.

Ciò è evidenziato in modo più dettagliato in questa Domande e risposte dal titolo: Come impostare una proprietà Spring Boot con un carattere di sottolineatura nel suo nome tramite Variabili d'ambiente?

Riferimenti


1

Può essere fatto usando il servizio Systemd in 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

Puoi seguire questo link per una descrizione più elaborata e diversi modi per farlo. http://www.baeldung.com/spring-boot-app-as-a-service


1

Crea uno script con il nome your-app.service (rest-app.service). Dovremmo mettere questo script nella directory / etc / systemd / system. Ecco il contenuto di esempio dello 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

Il prossimo:

 service rest-app start

Riferimenti

inserisci qui la descrizione del link


Sembra lo stesso come questo -> stackoverflow.com/a/30497095/516167
MariuszS
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.