it-swarm.com.de

Führen Sie eine Java-Anwendung als Dienst unter Linux aus

Ich habe eine Java-Serveranwendung geschrieben, die auf einer virtuellen Linux-Standardlösung ausgeführt wird. Die Anwendung läuft ständig auf Socketverbindungen und erstellt neue Handler für sie. Es ist eine serverseitige Implementierung für eine Client-Server-Anwendung.

Ich starte es so, dass ich es in das Startup rc.local script des Servers einfüge. Nach dem Start weiß ich jedoch nicht, wie ich darauf zugreifen kann, und wenn ich ein Update installieren möchte, muss ich den Server neu starten, um die Anwendung neu zu starten.

Auf einem Windows-PC kann ich für diese Art von Anwendung möglicherweise einen Windows-Dienst erstellen. Anschließend kann ich ihn anhalten und nach Belieben starten. Gibt es so etwas in einer Linux-Box, so dass ich sie starten und neu starten kann, ohne den Server neu starten zu müssen, wenn ich diese Anwendung starte.

Meine Anwendung heißt WebServer.exe. Es wird beim Start des Servers gestartet, indem es in mein rc.local aufgenommen wird:

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

Ich bin ein bisschen verrückt nach Linux, also wäre jedes Beispiel für alle Beiträge dankbar. Ich habe jedoch SSH und vollen FTP-Zugriff auf die Box, um Updates zu installieren und auf ein Plesk-Panel zuzugreifen.

114
dreza

Ich habe hier noch einen einfachen Wrapper geschrieben:

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

Sie können ein vollständiges Tutorial für init.d hier und für systemd (ubuntu 16 +) hier verfolgen.

Wenn Sie das Ausgabeprotokoll benötigen, ersetzen Sie den 2

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

zeilen für

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

Eine einfache Lösung ist das Erstellen eines Skripts start.sh, das Java über Nohup ausführt und dann die PID in einer Datei speichert:

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

Dann würde Ihr Stopp-Skript stop.sh die PID aus der Datei lesen und die Anwendung beenden:

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

Natürlich habe ich einige Details ausgelassen, wie zum Beispiel die Überprüfung, ob der Prozess existiert, und pid.txt entfernen, wenn Sie fertig sind.

45
Wernsey

Das Linux-Service-Init-Skript wird in /etc/init.d gespeichert. Sie können die /etc/init.d/skeleton-Datei kopieren und anpassen und dann aufrufen

service [yourservice] start|stop|restart

siehe http://www.ralfebert.de/blog/Java/debian_daemon/ . Es ist für Debian (also auch für Ubuntu), passt aber mehr in die Distribution.

32
Arcadien

Vielleicht nicht die beste Dev-Ops-Lösung, aber gut für die allgemeine Verwendung eines Servers für eine LAN-Party oder ähnliches.

Verwenden Sie screen, um Ihren Server auszuführen und abzutrennen, bevor Sie sich abmelden. Dadurch wird der Prozess weiter ausgeführt. Sie können ihn dann jederzeit wieder anschließen.

Arbeitsablauf:

Starten Sie einen Bildschirm: screen

Starten Sie Ihren Server: Java -jar minecraft-server.jar

Trennen Sie durch Drücken von: Ctl-a, d

Wieder anhängen: screen -r

Mehr Infos hier: https://www.gnu.org/software/screen/manual/screen.html

10
Peter Peterson

Eine andere, sehr beliebte Alternative ist der Java Service Wrapper . Dies ist auch in der OSS-Community sehr beliebt.

7
carlspring

In Bezug auf Spring Boot-Anwendung als Service würde ich auch die Version systemd wählen, da dies die einfachste, am wenigsten ausführliche und am besten in moderne Distros (und sogar die nicht so modernen Distributionen wie CentOS 7) ist .x).

5
yglodt

Hier ein Beispiel-Shell-Skript (stellen Sie sicher, dass Sie den MATH-Namen durch den Namen Ihrer Anwendung ersetzen)

#!/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
4
Alan Thompson

Von Spring Boot-Anwendung als Dienst kann ich die auf Python basierende supervisord-Anwendung empfehlen. Weitere Informationen finden Sie in dieser Stack Overflow-Frage. Es ist sehr einfach einzurichten.

3
DuffJ

Sie können Thrift-Server oder JMX verwenden, um mit Ihrem Java-Dienst zu kommunizieren.

1
tienthanhakay

Um Java-Code als Daemon (Dienst) auszuführen, können Sie einen JNI-basierten Stub schreiben.

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

für einen Beispielcode, der auf JNI basiert. In diesem Fall dämonisieren Sie den als Java gestarteten Code und die Hauptschleife wird in C ausgeführt. Es ist jedoch auch möglich, die Hauptschleife des Daemons in Java zu integrieren.

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

Viel Spaß mit JNI!

1
Oo.oO

Andere Antworten sind gut, wenn Sie benutzerdefinierte Skripts und Setups erstellen, je nach Plattform. Neben diesen sind hier die ausgereiften Spezialprogramme, die ich kenne:

  • JSW von TanukiSoftware
  • YAJSW ist ein Open-Source-Klon von oben. Es ist in Java geschrieben und ist ein Kindermädchen-Prozess, der den untergeordneten Prozess (Ihren Code) gemäß den Konfigurationen verwaltet. Funktioniert unter Windows/Linux.
  • JSVC ist eine native Anwendung. Es ist auch ein Kindermädchen-Prozess, aber es ruft Ihre Kinderanwendung über die JNI auf und nicht als Unterprozess.
1
Mori Bellamy

Einmal gestartet, weiß ich nicht, wie ich darauf zugreifen kann, um es zu stoppen

Sie können ein einfaches Stoppskript schreiben, das für Ihren Java-Prozess greift, die PID extrahiert und den Befehl kill dazu auffordert. Es ist nicht schick, aber es ist geradlinig . So etwas mag als Anfang hilfreich sein:

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

From Spring Boot Referenzhandbuch

Installation als init.d-Dienst (System V)

Verknüpfen Sie einfach das Jar mit init.d, um die Standardbefehle start, stop, restart und status zu unterstützen . Wenn Sie in/var/myapp eine Spring Boot-Anwendung installiert haben, erstellen Sie zur Installation einer Spring Boot-Anwendung als init.d-Dienst einfach einen Symlink:

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

Nach der Installation können Sie den Dienst wie gewohnt starten und stoppen. Zum Beispiel auf einem Debian-basierten System:

$ service myapp start

 Tip Wenn Ihre Anwendung nicht startet, überprüfen Sie die in /var/log/<appname>.log geschriebene Protokolldatei auf Fehler.

Lesen Sie weiter um zu wissen, wie Sie einen bereitgestellten Dienst sichern können.

Nach dem Schreiben habe ich festgestellt, dass mein Dienst mit dieser Fehlermeldung in den Protokollen nicht gestartet werden kann: start-stop-daemon: nicht erkannte Option --no-close . Und ich habe es geschafft, das Problem zu beheben, indem ich eine Konfigurationsdatei /var/myapp/myapp.conf mit folgendem Inhalt erstellt habe

USE_START_STOP_DAEMON=false
0
naXa

Es ist möglich, den War als Linux-Dienst auszuführen, und Sie möchten möglicherweise die pom.xml-Datei vor dem Packen erzwingen, da einige Distributionen dies im automatischen Modus möglicherweise nicht erkennen. Fügen Sie dazu die folgende Eigenschaft in das Plugin spring-boot-maven-plugin ein.

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

Als nächstes richten Sie Ihre init.d ein mit:

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

und du wirst rennen können

service myapp start|stop|restart

Es gibt viele andere Optionen, die Sie in Spring Boot-Dokumentation finden, einschließlich des Windows-Dienstes.

0
Eder Luis Jorge