web-dev-qa-db-fra.com

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

J'ai écrit une application serveur Java qui s'exécute sur une solution Linux hébergée virtuelle standard. L'application s'exécute tout le temps en écoutant les connexions de sockets et en créant de nouveaux gestionnaires pour celles-ci. C'est une implémentation côté serveur pour une application client-serveur.

Je commence par l'inclure dans le script de démarragerc.local du serveur. Cependant, une fois démarré, je ne sais pas comment y accéder pour l'arrêter et si je souhaite installer une mise à jour, je dois donc redémarrer le serveur pour pouvoir redémarrer l'application.

Sur un PC Windows, pour ce type d'application, je pourrais créer un service Windows, puis l'arrêter et le démarrer comme je le souhaite. Y at-il quelque chose comme ça sur une machine Linux afin que si je lance cette application je puisse l’arrêter et la redémarrer sans faire un redémarrage complet du serveur.

Mon application s'appelle WebServer.exe. Il est démarré au démarrage du serveur en l'incluant dans mon rc.local en tant que tel:

Java -jar /var/www/vhosts/myweb.com/phpserv/WebServer.jar &

Je suis un peu un noob à Linux donc tout exemple serait apprécié avec n'importe quel message. Cependant, j'ai SSH et un accès FTP complet à la boîte pour installer les mises à jour, ainsi que l'accès à un panneau Plesk.

114
dreza

J'ai écrit un autre simple wrapper ici:

#!/bin/sh
SERVICE_NAME=MyService
PATH_TO_JAR=/usr/local/MyProject/MyJar.jar
PID_PATH_NAME=/tmp/MyService-pid
case $1 in
    start)
        echo "Starting $SERVICE_NAME ..."
        if [ ! -f $PID_PATH_NAME ]; then
            Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
            echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is already running ..."
        fi
    ;;
    stop)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stoping ..."
            kill $PID;
            echo "$SERVICE_NAME stopped ..."
            rm $PID_PATH_NAME
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
    restart)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stopping ...";
            kill $PID;
            echo "$SERVICE_NAME stopped ...";
            rm $PID_PATH_NAME
            echo "$SERVICE_NAME starting ..."
            Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &
            echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
esac 

Vous pouvez suivre un tutoriel complet pour init.d here et pour systemd (ubuntu 16 +) here

Si vous avez besoin du journal de sortie, remplacez le 2

Nohup Java -jar $PATH_TO_JAR /tmp 2>> /dev/null >> /dev/null &

lignes pour

Nohup Java -jar $PATH_TO_JAR >> myService.out 2>&1&
225
PbxMan

Une solution simple consiste à créer un script start.sh qui exécute Java via Nohup, puis stocke le PID dans un fichier:

Nohup Java -jar myapplication.jar > log.txt 2> errors.txt < /dev/null &
PID=$!
echo $PID > pid.txt

Ensuite, votre script d'arrêt stop.sh lirait le PID du fichier et tuerait l'application:

PID=$(cat pid.txt)
kill $PID

Bien sûr, j'ai omis certains détails, tels que la vérification de l'existence du processus et la suppression de pid.txt si vous avez terminé.

45
Wernsey

Les scripts d'initialisation du service Linux sont stockés dans /etc/init.d. Vous pouvez copier et personnaliser le fichier /etc/init.d/skeleton, puis appeler

service [yourservice] start|stop|restart

voir http://www.ralfebert.de/blog/Java/debian_daemon/ . C'est pour Debian (donc, Ubuntu aussi) mais pour plus de distribution.

32
Arcadien

Peut-être pas la meilleure solution de dev-ops, mais bon pour l’utilisation générale d’un serveur pour un groupe local ou similaire.

Utilisez screen pour exécuter votre serveur, puis détachez-le avant de vous déconnecter. Le processus continuera de fonctionner, vous pourrez alors vous reconnecter à tout moment.

Flux de travail:

Lancer un écran: screen

Démarrez votre serveur: Java -jar minecraft-server.jar

Détachez en appuyant sur: Ctl-a, d

Re-attacher: screen -r

Plus d'infos ici: https://www.gnu.org/software/screen/manual/screen.html

10
Peter Peterson

Une autre alternative, qui est également très populaire, est le Java Service Wrapper . Ceci est également très populaire dans la communauté des logiciels libres.

7
carlspring

En se référant à l'application Spring Boot en tant que service , j'opterais également pour la version systemd, puisqu'elle est la plus facile, la moins détaillée et la mieux intégrée dans les distributions modernes (et même les moins modernes, comme CentOS 7 .X).

5
yglodt

Voici un exemple de script Shell (assurez-vous de remplacer le nom MATH par le nom de votre application):

#!/bin/bash

### BEGIN INIT INFO
# Provides:                 MATH
# Required-Start:           $Java
# Required-Stop:            $Java
# Short-Description:        Start and stop MATH service.
# Description:              -
# Date-Creation:            -
# Date-Last-Modification:   -
# Author:                   -
### END INIT INFO

# Variables
PGREP=/usr/bin/pgrep
Java=/usr/bin/Java
ZERO=0

# Start the MATH
start() {
    echo "Starting MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        echo "The service is already running"
    else
        #Run the jar file MATH service
        $Java -jar /opt/MATH/MATH.jar > /dev/null 2>&1 &
        #sleep time before the service verification
        sleep 10
        #Verify if the service is running
        $PGREP -f MATH  > /dev/null
        VERIFIER=$?
        if [ $ZERO = $VERIFIER ]
        then
            echo "Service was successfully started"
        else
            echo "Failed to start service"
        fi
    fi
    echo
}

# Stop the MATH
stop() {
    echo "Stopping MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        #Kill the pid of Java with the service name
        kill -9 $($PGREP -f MATH)
        #Sleep time before the service verification
        sleep 10
        #Verify if the service is running
        $PGREP -f MATH  > /dev/null
        VERIFIER=$?
        if [ $ZERO = $VERIFIER ]
        then
            echo "Failed to stop service"
        else
            echo "Service was successfully stopped"
        fi
    else
        echo "The service is already stopped"
    fi
    echo
}

# Verify the status of MATH
status() {
    echo "Checking status of MATH..."
    #Verify if the service is running
    $PGREP -f MATH > /dev/null
    VERIFIER=$?
    if [ $ZERO = $VERIFIER ]
    then
        echo "Service is running"
    else
        echo "Service is stopped"
    fi
    echo
}

# Main logic
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status
        ;;
    restart|reload)
        stop
        start
        ;;
  *)
    echo $"Usage: $0 {start|stop|status|restart|reload}"
    exit 1
esac
exit 0
4
Matheus Oliveira
4
Alan Thompson

À partir de Application Spring Boot en tant que service , je peux recommander l'application supervisord basée sur Python. Voir cette question de débordement de pile pour plus d'informations. C'est vraiment simple à mettre en place.

3
DuffJ

Vous pouvez utiliser Thrift server ou JMX pour communiquer avec votre service Java.

1
tienthanhakay

Pour exécuter le code Java en tant que démon (service), vous pouvez écrire un stub basé sur JNI.

http://jnicookbook.owsiak.org/recipe-no-022/

pour un exemple de code basé sur JNI. Dans ce cas, vous démonalisez le code qui a été lancé en tant que Java et la boucle principale est exécutée en C. Mais il est également possible de placer la boucle de service principale du démon dans Java.

https://github.com/mkowsiak/jnicookbook/tree/master/recipeNo029

Amusez-vous avec JNI!

1
Oo.oO

D'autres réponses font du bon travail en donnant des scripts personnalisés et des configurations en fonction de votre plate-forme. En plus de ceux-ci, voici les programmes matures et spéciaux que je connais:

  • JSW de TanukiSoftware
  • YAJSW est un clone open source du précédent. Il est écrit en Java et est un processus de nounou qui gère le processus enfant (votre code) en fonction des configurations. Fonctionne sur Windows/Linux.
  • JSVC est une application native. C'est aussi un processus de nounou, mais il appelle votre application enfant par le biais de JNI, plutôt que comme un sous-processus.
1
Mori Bellamy

Cependant, une fois commencé, je ne sais pas comment y accéder pour l'arrêter

Vous pouvez écrire un script d'arrêt simple qui écrit pour votre processus Java, extrait le PID et appelle kill sur celui-ci. Ce n'est pas compliqué, mais c'est simple ... Un début comme ça peut être utile au début:

#!/bin/bash
PID = ps ax | grep "name of your app" | cut -d ' ' -f 1
kill $PID
0
hovanessyan

From Guide de référence du démarrage du printemps

Installation en tant que service init.d (System V)

Reliez simplement jar le fichier jar à init.d pour prendre en charge les commandes standard start, stop, restart et status . En supposant qu'une application Spring Boot soit installée dans/var/myapp, pour installer une application Spring Boot en tant que service init.d, créez simplement un lien symbolique:

$ Sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp

Une fois installé, vous pouvez démarrer et arrêter le service de la manière habituelle. Par exemple, sur un système basé sur Debian:

$ service myapp start

 Tip Si votre application ne parvient pas à démarrer, vérifiez si le fichier journal écrit dans /var/log/<appname>.log contient des erreurs.

Poursuivez votre lecture pour savoir comment sécuriser un service déployé.

Après avoir procédé comme prévu, j'ai découvert que mon service ne pouvait pas démarrer avec ce message d'erreur dans les journaux: start-stop-daemon: option non reconnue --no-close . Et j'ai réussi à le réparer en créant un fichier de configuration /var/myapp/myapp.conf avec le contenu suivant

USE_START_STOP_DAEMON=false
0
naXa

Il est possible d’exécuter la guerre en tant que service Linux et vous pouvez forcer le fichier pom.xml à être forcé avant l’emballage, car certaines distributions risquent de ne pas être reconnues en mode automatique. Pour ce faire, ajoutez la propriété suivante à l’intérieur du plug-in spring-boot-maven-plugin.

                    <embeddedLaunchScriptProperties>
                        <mode>service</mode>
                    </embeddedLaunchScriptProperties>

Ensuite, configurez votre init.d avec:

ln -s myapp.war /etc/init.d/myapp

et vous pourrez courir

service myapp start|stop|restart

Il existe de nombreuses autres options que vous pouvez trouver dans Documentation Spring Boot , y compris le service Windows.

0
Eder Luis Jorge