Application Spring Boot en tant que service

197

Comment configurer joliment l'application Spring Boot empaquetée sous forme de pot exécutable en tant que service dans un système Linux? Est-ce l'approche recommandée, ou devrais-je convertir cette application en guerre et l'installer dans Tomcat?

Actuellement, je peux exécuter l'application de démarrage Spring à partir de la screensession, ce qui est bien, mais nécessite un démarrage manuel après le redémarrage du serveur.

Ce que je suis à la recherche est des conseils généraux / direction ou un échantillon de init.dscript, si mon approche avec exécutable pot est propre.

MariuszS
la source
Pour commencer, votre distribution utilise-t-elle upstart ou systemd?
yglodt

Réponses:

138

Les travaux suivants pour Springboot 1.3 et supérieur:

En tant que service init.d

Le fichier exécutable contient les commandes habituelles de démarrage, d'arrêt, de redémarrage et d'état. Il configurera également un fichier PID dans le répertoire habituel / var / run et se connectera par défaut dans le répertoire habituel / var / log.

Il vous suffit de créer un lien symbolique entre votre pot et /etc/init.d comme ceci

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

Après cela, vous pouvez faire l'habituel

/etc/init.d/myapp start

Ensuite, configurez un lien dans le niveau d'exécution dans lequel vous souhaitez que l'application démarre / s'arrête au démarrage si vous le souhaitez.


En tant que service systemd

Pour exécuter une application Spring Boot installée dans var / myapp, vous pouvez ajouter le script suivant dans /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

NB: dans le cas où vous utilisez cette méthode, n'oubliez pas de rendre le fichier jar lui-même exécutable (avec chmod + x) sinon il échouera avec l'erreur "Autorisation refusée".

Référence

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

tchad
la source
1
Comment fonctionne l'approche "JAR entièrement exécutable"? J'utilise CentOS 6.6. J'ai ajouté <executable>true</executable>à mon pom.xml, mais le fichier JAR empaqueté ne s'exécute pas (.... ./myapp.jar ... cannot execute binary file)
Abdull
5
Cette réponse ne fonctionne que pour l'actuel 1.3 Milestone, qui n'est pas encore publié. Les succursales 1.1 et 1.2 devront vérifier les autres réponses ici.
pour le
6
Savez-vous les gars comment passer les arguments du printemps tels que -Dspring.profiles.active=prodces services? Question - stackoverflow.com/questions/31242291/…
nKognito
2
Je ne parviens pas à arrêter l'application Spring-Boot. /etc/init.d stopn'arrête pas l'application, elle essaie de la redémarrer.
tintin
2
Si vous souhaitez surveiller le processus et le redémarrer s'il meurt sans écrire les démons du système, consultez patrickgrimard.com/2014/06/06/…
ruX
112

Ce qui suit est le moyen le plus simple d'installer une application Java en tant que service système sous Linux.

Supposons que vous utilisez systemd(ce que fait n'importe quelle distribution moderne de nos jours):

Tout d'abord, créez un fichier de service dans /etc/systemd/systemnommé par exemple javaservice.serviceavec ce contenu:

[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

Deuxièmement, notifiez systemdle nouveau fichier de service:

systemctl daemon-reload

et l'activer, donc il s'exécute au démarrage:

systemctl enable javaservice.service

Finalement, vous pouvez utiliser les commandes suivantes pour démarrer / arrêter votre nouveau service:

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

À condition que vous l'utilisiez systemd, c'est la manière la plus simple et la moins intrusive de configurer une application Java en tant que service système.

Ce que j'aime particulièrement dans cette solution, c'est que vous n'avez pas besoin d'installer et de configurer d'autres logiciels. L'expéditeur systemdfait tout le travail pour vous et votre service se comporte comme n'importe quel autre service système. Je l'utilise en production depuis un moment maintenant, sur différentes distributions, et cela fonctionne comme vous vous en doutez.

Un autre avantage est que, en utilisant /usr/bin/java, vous pouvez facilement ajouter des jvmparamètres tels que -Xmx256m.

Lisez également la systemdpartie dans la documentation officielle de Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

yglodt
la source
Malheureusement, systemd n'est pas disponible pour Centos 6
MariuszS
comment sait-il comment l'arrêter? Enregistre le pid puis le tue?
brume
2
Avec Spring Boot 1.3+, vous pouvez générer un fichier war entièrement exécutable, donc pas besoin du bit java -jar ..., utilisez simplement le nom du fichier.
Pierre Henry
1
Je préfère utiliser la ligne de commande java complète car de cette façon, vous pouvez ajouter des paramètres jvm.
yglodt
1
Pour une séquence de démarrage appropriée , vous pouvez ajouter des instructions de commande à la [Unit]section, par exemple After=mysql.service, Before=apache2.service.
rustyx
57

Vous pouvez également utiliser supervisord qui est un démon très pratique, qui peut être utilisé pour contrôler facilement les services. Ces services sont définis par de simples fichiers de configuration définissant ce qu'il faut exécuter avec quel utilisateur dans quel répertoire et ainsi de suite, il existe une multitude d'options. supervisord a une syntaxe très simple, c'est donc une très bonne alternative à l'écriture de scripts d'initialisation SysV.

Voici simple supervisord fichier de configuration pour le programme que vous essayez d'exécuter / contrôle. (mettez-le dans /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

Pour contrôler l'application, vous devez exécuter supervisorctl , qui vous présentera une invite à partir de laquelle vous pourrez démarrer, arrêter et indiquer votre application.

CLI

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

Si la supervisord démon est déjà en cours d'exécution et que vous avez ajouté la configuration de votre service sans redémarrer le démon, vous pouvez simplement faire une commande rereadet updatedans lesupervisorctl shell.

Cela vous donne vraiment toutes les flexibilité que vous auriez avec les scripts SysV Init, mais faciles à utiliser et à contrôler. Jetez un œil à la documentation .

flazzarini
la source
Enfin, quelque chose a fonctionné pour moi dès la sortie de la boîte. Merci beaucoup pour le conseil de supervisord.
Vitaly Sazanovich
Cela fait le même travail que celui systemdqui est intégré dans la plupart des distributions Linux actuelles.
rustyx
18

Je viens de le faire moi-même, donc voici où je suis jusqu'à présent en termes de script de contrôleur de service CentOS init.d. Cela fonctionne très bien jusqu'à présent, mais je ne suis pas un hacker Let Bash, donc je suis sûr qu'il y a place à amélioration, donc les réflexions sur l'amélioration sont les bienvenues.

Tout d'abord, j'ai un court script de configuration /data/svcmgmt/conf/my-spring-boot-api.shpour chaque service, qui définit les variables d'environnement.

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

J'utilise CentOS, donc pour m'assurer que mes services sont démarrés après un redémarrage du serveur, j'ai un script de contrôle de service dans /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

Comme vous pouvez le voir, cela appelle le script de configuration initial pour configurer les variables d'environnement, puis appelle un script partagé que j'utilise pour redémarrer tous mes services Spring Boot. Ce script partagé est l'endroit où la viande de tout cela peut être trouvée:

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

Lors de l'arrêt, il tentera d'utiliser Spring Boot Actuator pour effectuer un arrêt contrôlé. Cependant, dans le cas où Actuator n'est pas configuré ou ne s'arrête pas dans un délai raisonnable (je lui donne 5 secondes, ce qui est vraiment un peu court), le processus sera tué.

De plus, le script suppose que le processus java exécutant l'application sera le seul avec "my-spring-boot-api.jar" dans le texte des détails du processus. Ceci est une hypothèse sûre dans mon environnement et signifie que je n'ai pas besoin de garder une trace des PID.

Steve
la source
3
Pas besoin d'écrire votre propre script de démarrage / arrêt. Ceci est fourni à partir de Spring Boot 1.3 et plus. Voir docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… pour plus de détails.
gregturn
Bon à savoir que c'est une option, mais tout ce qu'il fait est de supprimer la nécessité d'exécuter à l'aide de java -jar. Le reste du script est toujours nécessaire.
Steve
Très utile lorsque /etc/init.d ou systemd n'est pas une option, merci pour le partage.
bernardn
@Steve: Non. Vous réinventez la roue. Oh, et nous avons systemd maintenant.
Martin Schröder
Lorsque vous devez passer des paramètres à la JVM (comme les paramètres -javaagent ou -D), c'est la manière unique, tks @Steve!
Dyorgio
14

Si vous souhaitez utiliser Spring Boot 1.2.5 avec Spring Boot Maven Plugin 1.3.0.M2, voici la solution:

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

Compilez ensuite comme d'habitude:, mvn clean packagecréez un lien symbolique ln -s /.../myapp.jar /etc/init.d/myapp, rendez-le exécutable chmod +x /etc/init.d/myappet démarrez-le service myapp start(avec Ubuntu Server)

Benjamin M
la source
qu'en est-il des fichiers WAR exécutables? cela ne fonctionne pas pour moi avec la disposition WAR.
Radu Toader
Fait intéressant, cela fonctionne avec la version 1.3.0.M2, mais j'ai eu une erreur lorsque j'ai essayé 1.3.0.RC1.
JBCP
Une idée sur la façon de le faire avec gradle au lieu de maven?
Geir
Lors de l'utilisation de Gradle, cette configuration se fait à l'aide d'un springBoot { executable = true }bloc.
Natix
@RaduToader: Avez-vous pu exécuter le fichier WAR en tant que service?
naveenkumarbv
9

Je sais que c'est une question plus ancienne, mais je voulais présenter une autre manière qui est le plugin appassembler-maven . Voici la partie pertinente de mon POM qui comprend de nombreuses valeurs d'options supplémentaires que nous avons trouvées utiles:

<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
la source
6

EN TANT QUE SERVICE WINDOWS

Si vous voulez que cela s'exécute dans la machine Windows, téléchargez le winsw.exe à partir de

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

Après cela, renommez-le en nom de fichier jar (par exemple: votre-app .jar)

winsw.exe -> your-app.exe

Créez maintenant un fichier xml your-app.xml et copiez le contenu suivant dans celui-ci

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

Assurez-vous que l' exe et le xml avec le pot dans un même dossier.

Après cette invite de commande ouverte dans le privilège Administrateur et installez-la sur le service Windows.

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

En cas d'échec avec

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

Essayez ensuite ce qui suit:

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

c'est tout :) .

Pour désinstaller le service dans Windows

your-app.exe uninstall

Pour voir / exécuter / arrêter le service: win + r et tapez Outils d'administration, puis sélectionnez le service à partir de cela. Cliquez ensuite avec le bouton droit de la souris sur l' option - exécuter / arrêter

Arundev
la source
J'ai suivi les mêmes étapes pour exécuter le pot de démarrage de printemps en tant que service Windows dans l'intranet de l'entreprise, mais le service ne démarre pas. Une fenêtre s'affiche avec une erreur: Erreur: 1067 Le processus s'est terminé de manière inattendue Pourriez-vous s'il vous plaît aider ou suggérer ce qui doit être fait?
Nikhil Singh Bhadoriya
Avez-vous toutes les autorisations pour le faire? Si vous êtes administrateur, cela ne posera aucun problème. Pouvez-vous vérifier que vous disposez des droits d'administrateur.
Arundev
stackoverflow.com/questions/18205111/… pouvez-vous s'il vous plaît essayer cela peut être cela vous aidera à résoudre le problème.
Arundev
merci pour la réponse rapide, j'ai rendu mon service opérationnel en corrigeant un problème avec la balise dans le fichier xml.
Nikhil Singh Bhadoriya
4

Mon script SysVInit pour Centos 6 / RHEL (pas encore idéal). Ce script nécessite ApplicationPidListener .

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

Exemple de fichier de configuration /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
la source
4

Voici un script qui déploie un pot exécutable en tant que service systemd.

Il crée un utilisateur pour le service et le fichier .service, place le fichier jar sous / var et effectue un verrouillage de base des privilèges.

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

Exemple: entrez la description de l'image ici

Utilisateur0
la source
4

J'essaie de créer des applications Springboot qui sont présentées comme un script shell de style "init.d" avec une application Java compressée clouée à la fin

En associant ces scripts de /etc/init.d/spring-app à /opt/spring-app.jar et en chmodant le pot pour être exécutable, il est possible de faire démarrer "/etc/init.d/spring-app" "" /etc/init.d/spring-app stop "et d'autres possibilités comme le travail d'état

Vraisemblablement, comme les scripts de style init.d de springboot semblent avoir les cordes magiques nécessaires (comme # Default-Start: 2 3 4 5 ), chkconfig pourrait l'ajouter en tant que "service"

Mais je voulais le faire fonctionner avec systemd

Pour que cela fonctionne, j'ai essayé de nombreuses recettes dans les autres réponses ci-dessus, mais aucune n'a fonctionné pour moi sur Centos 7.2 avec Springboot 1.3. La plupart du temps, elles allaient démarrer le service mais ne pouvaient pas suivre le pid

En fin de compte, j'ai trouvé que ce qui suit fonctionnait pour moi, lorsque le lien /etc/init.d était également en place. Un fichier similaire à celui ci-dessous doit être installé en tant que/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
la source
4

J'ai fini par faire le service systemd pour la mise en page WAR / JAR

J'appelle java -jar parce que c'est plus flexible. J'ai aussi essayé de mettre ExecStart = spring-mvc.war mais même s'il est exécutable, j'ai eu 'Erreur de format Exec'

Quoi qu'il en soit ces jours-ci, systemd est présent sur toutes les distributions et offre une bonne solution pour rediriger les journaux (syserr est important lorsque votre service ne démarre même pas l'emplacement du fichier log4j sera vide :)).

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 - redirige l'entrée syslog de l'application vers un dossier / fichier spécifique

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
la source
3

Dans cette question, la réponse de @PbxMan devrait vous aider à démarrer:

Exécuter une application Java en tant que service sous Linux

Éditer:

Il existe une autre façon, moins agréable, de démarrer un processus au redémarrage, en utilisant cron:

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

Cela fonctionne, mais ne vous donne pas d'interface de démarrage / d'arrêt agréable pour votre application. Vous pouvez toujours le killfaire de toute façon ...

yglodt
la source
Pas vraiment, car Spring Boot offre des fonctionnalités spéciales pour ce faire.
Tristan
2

Je ne connais pas de façon standard de le faire avec une application Java, mais c'est certainement une bonne idée (vous voulez bénéficier des capacités de survie et de surveillance du système d'exploitation si elles sont là) . Il est sur la feuille de route pour fournir quelque chose à partir du support de l'outil Spring Boot (maven et gradle), mais pour le moment, vous devrez probablement lancer le vôtre. La meilleure solution que je connaisse actuellement est Foreman , qui a une approche déclarative et des commandes d'une ligne pour empaqueter les scripts init pour différents formats de système d'exploitation standard (monit, sys V, upstart, etc.). Il existe également des preuves de personnes ayant installé des trucs avec gradle (par exemple ici ).

Dave Syer
la source
2

Utilisez-vous Maven? Ensuite, vous devriez essayer le plug-in AppAssembler:

Le plugin Application Assembler est un plugin Maven permettant de générer des scripts pour démarrer des applications java. ... Tous les artefacts (dépendances + l'artefact du projet) sont ajoutés au chemin de classe dans les scripts bin générés.

Plateformes prises en charge:

Variantes Unix

Windows NT (Windows 9x n'est PAS pris en charge)

Java Service Wrapper (JSW)

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

d0x
la source
2

La configuration suivante est requise dans le fichier build.gradle des projets Spring Boot.

build.gradle

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

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

exécutable = vrai

Cela est nécessaire pour créer un pot entièrement exécutable sur le système Unix (Centos et Ubuntu)

Créez un fichier .conf

Si vous souhaitez configurer des propriétés JVM personnalisées ou des arguments d'exécution d'application Spring Boot, vous pouvez créer un fichier .conf avec le même nom que le nom de l'application Spring Boot et le placer parallèlement au fichier jar.

Étant donné que your-app.jar est le nom de votre application Spring Boot, vous pouvez créer le fichier suivant.

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

Cette configuration définira 64 Mo de RAM pour l'application Spring Boot et activera le profil prod.

Créer un nouvel utilisateur sous Linux

Pour une sécurité renforcée, nous devons créer un utilisateur spécifique pour exécuter l'application Spring Boot en tant que service.

Créer un nouvel utilisateur

sudo useradd -s /sbin/nologin springboot

Sur Ubuntu / Debian, modifiez la commande ci-dessus comme suit:

sudo useradd -s /usr/sbin/nologin springboot

Définir le mot de passe

sudo passwd springboot

Rendre Springboot propriétaire du fichier exécutable

chown springboot:springboot your-app.jar

Empêcher la modification du fichier jar

chmod 500 your-app.jar

Cela configurera les autorisations de jar afin qu'il ne puisse pas être écrit et ne puisse être lu ou exécuté que par son propriétaire springboot.

Vous pouvez éventuellement rendre votre fichier jar immuable en utilisant la commande change attribute (chattr).

sudo chattr +i your-app.jar

Des autorisations appropriées doivent également être définies pour le fichier .conf correspondant. .conf nécessite juste un accès en lecture (Octal 400) au lieu d'un accès en lecture + exécution (Octal 500)

chmod 400 your-app.conf

Créer un service 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

Redémarrez automatiquement le processus s'il est tué par le système d'exploitation

Ajoutez les deux attributs ci-dessous (Redémarrer et RestartSec) pour redémarrer automatiquement le processus en cas d'échec.

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

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

La modification fera redémarrer l'application Spring Boot en cas d'échec avec un retard de 30 secondes. Si vous arrêtez le service à l'aide de la commande systemctl, le redémarrage n'aura pas lieu.

Planifier le service au démarrage du système

Pour signaler que l'application démarre automatiquement au démarrage du système, utilisez la commande suivante:

Activer l'application Spring Boot au démarrage du système

sudo systemctl enable your-app.service

Démarrer un arrêt du service

systemctl peut être utilisé dans Ubuntu 16.04 LTS et 18.04 LTS pour démarrer et arrêter le processus.

Lancer le processus

sudo systemctl start your-app

Arrêtez le processus

sudo systemctl stop your-app

Références

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

ismael
la source
1

Suite à l'excellente réponse de Chad, si vous obtenez une erreur "Erreur: impossible de trouver ou de charger la classe principale" - et que vous passez quelques heures à essayer de le dépanner, que ce soit en exécutant un script shell qui démarre votre application java ou en le démarrant depuis systemd lui-même - et vous savez que votre chemin de classe est correct à 100%, par exemple, l'exécution manuelle du script shell fonctionne aussi bien que l'exécution de ce que vous avez dans systemd execstart. Assurez-vous que que vous exécutez les choses en tant qu'utilisateur correct! Dans mon cas, j'avais essayé différents utilisateurs, après un certain temps de dépannage - j'ai finalement eu une intuition, mis root comme utilisateur - le tour est joué, l'application a démarré correctement. Après avoir déterminé qu'il s'agissait d'un mauvais problème utilisateur, j'aichown -R user:user le dossier et les sous-dossiers et l'application s'exécutaient correctement en tant qu'utilisateur et groupe spécifiés, il n'était donc plus nécessaire de l'exécuter en tant que root (mauvaise sécurité).

JGlass
la source
1

Dans les fichiers d'unité systemd, vous pouvez définir le répertoire des variables d'environnement ou via un EnvironmentFile. Je proposerais de faire les choses de cette façon car cela semble être le moins de friction.

Exemple de fichier d'unité

$ 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

Configurez ensuite un fichier sous /etc/sysconfig/hello-worldlequel figurent les noms en majuscules de vos variables Spring Boot. Par exemple, une variable appelée server.portsuivrait le formulaire SERVER_PORTcomme une variable d'environnement:

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

Le mécanisme exploité ici est que les applications Spring Boot prennent la liste des propriétés, puis les traduisent, en mettant tout en majuscules et en remplaçant les points par des traits de soulignement. Une fois que l'application Spring Boot a suivi ce processus, elle recherche les variables d'environnement qui correspondent et utilise celles trouvées en conséquence.

Ceci est mis en évidence plus en détail dans ce SO Q&A intitulé: Comment définir une propriété Spring Boot avec un trait de soulignement dans son nom via les variables d'environnement?

Références

slm
la source
1

Cela peut être fait en utilisant le service Systemd dans 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

Vous pouvez suivre ce lien pour une description plus élaborée et différentes façons de le faire. http://www.baeldung.com/spring-boot-app-as-a-service

mujeeb rahman
la source
1

Créez un script avec le nom your-app.service (rest-app.service). Nous devons placer ce script dans le répertoire / etc / systemd / system. Voici l'exemple de contenu du 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

Prochain:

 service rest-app start

Références

entrez la description du lien ici

ismael
la source
Ressemble à ceci -> stackoverflow.com/a/30497095/516167
MariuszS