Spring Boot-Anwendung als Service


196

Wie konfiguriere ich eine Spring Boot-Anwendung, die als ausführbares JAR als Service in einem Linux-System verpackt ist? Ist dies ein empfohlener Ansatz oder sollte ich diese App in War konvertieren und in Tomcat installieren?

Derzeit kann ich die Spring-Boot-Anwendung von der screenSitzung aus ausführen , was nett ist, erfordert jedoch einen manuellen Start nach dem Neustart des Servers.

Was ich suche, ist ein allgemeiner Rat / eine Anleitung oder ein Beispielskript init.d, wenn mein Ansatz mit ausführbarem JAR richtig ist.


Verwendet Ihre Distribution zunächst upstart oder systemd?
Yglodt

Antworten:


137

Folgendes funktioniert für Springboot 1.3 und höher:

Als init.d Service

Das ausführbare JAR verfügt über die üblichen Befehle zum Starten, Stoppen, Neustarten und Status. Außerdem wird eine PID-Datei im üblichen Verzeichnis / var / run eingerichtet und standardmäßig im üblichen Verzeichnis / var / log angemeldet.

Sie müssen nur Ihr Glas wie folgt mit /etc/init.d verknüpfen

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

ODER

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

Danach können Sie das Übliche tun

/etc/init.d/myapp start

Richten Sie dann einen Link ein, in welchem ​​Runlevel die App beim Booten gestartet / gestoppt werden soll, falls dies gewünscht wird.


Als systemd Service

Um eine in var / myapp installierte Spring Boot-Anwendung auszuführen, können Sie das folgende Skript in /etc/systemd/system/myapp.service hinzufügen:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

NB: Wenn Sie diese Methode verwenden, vergessen Sie nicht, die JAR-Datei selbst ausführbar zu machen (mit chmod + x), da sie sonst mit dem Fehler "Berechtigung verweigert" fehlschlägt.

Referenz

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


1
Wie funktioniert der Ansatz "vollständig ausführbare JAR"? Ich benutze CentOS 6.6. Ich habe <executable>true</executable>zu meiner hinzugefügt pom.xml, aber die gepackte JAR-Datei wird nicht ausgeführt (.... ./myapp.jar ... cannot execute binary file)
Abdull

5
Diese Antwort funktioniert nur für den aktuellen 1.3-Meilenstein, der noch nicht veröffentlicht wurde. Die Zweige 1.1 und 1.2 müssen die anderen Antworten hier überprüfen.
voor

6
Wissen Sie, wie man die Argumente des Frühlings in Bezug -Dspring.profiles.active=prodauf diese Dienste weitergibt? Frage - stackoverflow.com/questions/31242291/…
nKognito

2
Ich kann die Spring-Boot-Anwendung nicht stoppen. /etc/init.d stopstoppt die App nicht, sondern versucht sie erneut zu starten.
Tim und Struppi

2
Wenn Sie den Prozess überwachen und neu starten möchten, wenn er stirbt, ohne Systemdämonen
Sie

112

Was folgt, ist der einfachste Weg, eine Java-Anwendung als Systemdienst unter Linux zu installieren.

Nehmen wir an, Sie verwenden systemd(was heutzutage jede moderne Distribution tut):

Erstellen Sie zunächst eine Servicedatei mit dem /etc/systemd/systemNamen zB javaservice.servicemit folgendem Inhalt:

[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

Zweitens benachrichtigen Sie systemdüber die neue Servicedatei:

systemctl daemon-reload

und aktivieren Sie es, damit es beim Booten ausgeführt wird:

systemctl enable javaservice.service

Schließlich können Sie die folgenden Befehle verwenden, um Ihren neuen Dienst zu starten / zu stoppen:

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

Vorausgesetzt, Sie verwenden systemd, ist dies die unaufdringlichste und sauberste Methode, um eine Java-Anwendung als Systemdienst einzurichten.

Was mir an dieser Lösung besonders gefällt, ist die Tatsache, dass Sie keine andere Software installieren und konfigurieren müssen. Der Versand systemderledigt die ganze Arbeit für Sie und Ihr Service verhält sich wie jeder andere Systemdienst. Ich benutze es jetzt schon eine Weile in der Produktion, auf verschiedenen Distributionen, und es funktioniert einfach so, wie Sie es erwarten würden.

Ein weiteres Plus ist, dass /usr/bin/javaSie mit einfach jvmParameter wie hinzufügen können -Xmx256m.

Lesen Sie auch den systemdTeil in der offiziellen Spring Boot-Dokumentation: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html


Leider ist systemd nicht verfügbar für Centos 6
MariuszS

Woher weiß es, wie man es aufhält? Nimmt die PID auf und tötet sie dann?
Nebel

2
Mit Spring Boot 1.3+ können Sie eine vollständig ausführbare War-Datei generieren, sodass Sie das Java-Jar-Bit nicht benötigen. Verwenden Sie einfach den Dateinamen dort.
Pierre Henry

1
Ich bevorzuge die Verwendung der vollständigen Java-Befehlszeile, da Sie auf diese Weise JVM-Parameter hinzufügen können.
Yglodt

1
Für eine korrekte Startreihenfolge sollten Sie Bestellung Aussagen zum hinzufügen [Unit]Abschnitt, zum Beispiel After=mysql.service, Before=apache2.service.
Rustyx

57

Sie können auch Supervisord verwenden , einen sehr praktischen Daemon, mit dem Sie Dienste einfach steuern können. Diese Dienste werden durch einfache Konfigurationsdateien definiert, die definieren, was mit welchem ​​Benutzer in welchem ​​Verzeichnis ausgeführt werden soll usw. Es gibt zig Optionen. Supervisord hat eine sehr einfache Syntax und ist daher eine sehr gute Alternative zum Schreiben von SysV-Init-Skripten.

Hier eine einfache Supervisord- Konfigurationsdatei für das Programm, das Sie ausführen / steuern möchten. ( Geben Sie dies in /etc/supervisor/conf.d/yourapp.conf ein. )

/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

Um die Anwendung zu steuern, müssten Sie Supervisorctl ausführen . Daraufhin wird eine Eingabeaufforderung angezeigt, in der Sie Ihre App starten, stoppen und den Status festlegen können.

CLI

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

Wenn der supervisordDämon bereits ausgeführt wird und Sie die Konfiguration für Ihre Dienstleistung hinzugefügt haben, ohne den Dämon neu zu starten, können Sie einfach einen Befehl rereadund updatein der supervisorctlShell ausführen .

Dies gibt Ihnen wirklich alle Flexibilität, die Sie mit SysV Init-Skripten hätten, aber einfach zu verwenden und zu steuern. Schauen Sie sich die Dokumentation an .


Endlich hat etwas für mich sofort funktioniert. Vielen Dank für den Supervisord-Hinweis.
Vitaly Sazanovich

Dies macht den gleichen Job wie systemdin den meisten aktuellen Linux-Distributionen.
Rustyx

18

Ich bin gerade erst dazu gekommen, dies selbst zu tun. Im Folgenden bin ich also in Bezug auf ein CentOS init.d Service Controller-Skript so weit. Bisher funktioniert es ganz gut, aber ich bin kein Bash-Hacker. Ich bin mir also sicher, dass es Raum für Verbesserungen gibt. Daher sind Überlegungen zur Verbesserung willkommen.

Zunächst habe ich /data/svcmgmt/conf/my-spring-boot-api.shfür jeden Dienst ein kurzes Konfigurationsskript , mit dem Umgebungsvariablen eingerichtet werden.

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

Ich verwende CentOS. Um sicherzustellen, dass meine Dienste nach einem Neustart des Servers gestartet werden, habe ich ein Dienststeuerungsskript 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

Wie Sie sehen, ruft dies das anfängliche Konfigurationsskript auf, um Umgebungsvariablen einzurichten, und ruft dann ein freigegebenes Skript auf, mit dem ich alle meine Spring Boot-Dienste neu starte. In diesem gemeinsamen Skript finden Sie das Fleisch von allem:

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

Beim Anhalten wird versucht, mit Spring Boot Actuator ein kontrolliertes Herunterfahren durchzuführen. Falls Actuator jedoch nicht konfiguriert ist oder nicht innerhalb eines angemessenen Zeitrahmens heruntergefahren werden kann (ich gebe ihm 5 Sekunden, was wirklich ein bisschen kurz ist), wird der Prozess abgebrochen.

Außerdem geht das Skript davon aus, dass der Java-Prozess, auf dem die Anwendung ausgeführt wird, der einzige mit "my-spring-boot-api.jar" im Text der Prozessdetails ist. Dies ist eine sichere Annahme in meiner Umgebung und bedeutet, dass ich die PIDs nicht verfolgen muss.


3
Sie müssen kein eigenes Start / Stopp-Skript schreiben. Dies ist ab Spring Boot 1.3 verfügbar. Weitere Informationen finden Sie unter docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… .
Gregturn

Gut zu wissen, dass dies eine Option ist, aber alles, was es tut, ist die Notwendigkeit der Ausführung mit zu beseitigen java -jar. Der Rest des Skripts wird noch benötigt.
Steve

Sehr nützlich, wenn /etc/init.d oder systemd keine Option ist, danke für das Teilen.
Bernardn

@Steve: Nein. Sie erfinden das Rad neu. Oh, und wir haben jetzt systemd.
Martin Schröder

Wenn Sie Parameter an JVM übergeben müssen (wie -javaagent- oder -D-Parameter), ist dies die einzigartige Methode, tks @Steve!
Dyorgio

14

Wenn Sie Spring Boot 1.2.5 mit dem Spring Boot Maven Plugin 1.3.0.M2 verwenden möchten, finden Sie hier eine Lösung:

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

Dann als üblich kompilieren : mvn clean package, einen Symlink erstellen ln -s /.../myapp.jar /etc/init.d/myapp, ausführbar machen chmod +x /etc/init.d/myappund starten service myapp start(mit Ubuntu Server)


Was ist mit ausführbaren WAR-Dateien? Bei WAR-Layout funktioniert das bei mir nicht.
Radu Toader

Interessanterweise funktioniert dies mit Release 1.3.0.M2, aber ich habe einen Fehler erhalten, als ich es versuchte 1.3.0.RC1.
JBCP

Irgendeine Idee, wie man das mit Gradle anstelle von Maven macht?
Geir

Bei Verwendung von Gradle erfolgt diese Konfiguration mithilfe von springBoot { executable = true }Block.
Natix

@ RaduToader: Konnten Sie die WAR-Datei als Dienst ausführen?
Naveenkumarbv

9

Ich weiß, dass dies eine ältere Frage ist, aber ich wollte noch einen anderen Weg vorstellen, nämlich das Appassembler-Maven-Plugin . Hier ist der relevante Teil aus meinem POM, der viele zusätzliche Optionswerte enthält, die wir als nützlich erachtet haben:

<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

ALS FENSTER-SERVICE

Wenn Sie möchten, dass dies auf einem Windows-Computer ausgeführt wird, laden Sie die Datei www.exe von herunter

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

Danach benennen Sie es in jar Dateiname um (zB: your-app .jar)

winsw.exe -> your-app.exe

Erstellen Sie nun eine XML-Datei your-app.xml und kopieren Sie den folgenden Inhalt in diese

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

Stellen Sie sicher, dass sich exe und xml zusammen mit jar in demselben Ordner befinden.

Öffnen Sie nach dieser Eingabeaufforderung die Administratorrechte und installieren Sie sie auf dem Windows-Dienst.

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

Wenn es mit fehlschlägt

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

Versuchen Sie dann Folgendes:

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

das ist es :) .

So deinstallieren Sie den Dienst in Windows

your-app.exe uninstall

Zum Anzeigen / Ausführen / Stoppen des Dienstes: win + r und geben Sie Verwaltung ein. Wählen Sie dann den Dienst aus. Klicken Sie dann mit der rechten Maustaste und wählen Sie die Option - Ausführen / Stoppen


Ich habe die gleichen Schritte ausgeführt, um Spring Boot Jar als Windows-Dienst in der Intranet-Umgebung des Unternehmens auszuführen, aber der Dienst wird nicht aufgerufen. Es erscheint ein Fenster mit dem folgenden Fehler: Fehler: 1067 Der Vorgang wurde unerwartet beendet. Könnten Sie bitte helfen oder vorschlagen, was zu tun ist?
Nikhil Singh Bhadoriya

Haben Sie die Erlaubnis dazu? Wenn Sie ein Administrator sind, verursacht dies keine Probleme. Können Sie bitte überprüfen, ob Sie Administratorrechte haben?
Arundev

stackoverflow.com/questions/18205111/… können Sie bitte versuchen, dies kann sein, dies wird Ihnen helfen, das Problem zu lösen.
Arundev

Vielen Dank für die schnelle Antwort. Ich habe meinen Dienst eingerichtet, indem ich ein Problem mit dem Tag in der XML-Datei behoben habe.
Nikhil Singh Bhadoriya

4

Mein SysVInit-Skript für Centos 6 / RHEL (noch nicht ideal). Dieses Skript erfordert ApplicationPidListener .

Quelle von /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 $?

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

Hier ist ein Skript, das eine ausführbare JAR-Datei als systemd-Dienst bereitstellt.

Es erstellt einen Benutzer für den Dienst und die .service-Datei, platziert die JAR-Datei unter / var und sperrt die Berechtigungen grundlegend.

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

Beispiel: Geben Sie hier die Bildbeschreibung ein


4

Ich versuche, Springboot-Anwendungen zu erstellen, die als Shell-Skript im "init.d" -Stil mit einer komprimierten Java-Anwendung am Ende dargestellt werden

Durch die Verknüpfung dieser Skripte von /etc/init.d/spring-app mit /opt/spring-app.jar und die Änderung der ausführbaren JAR-Datei kann "/etc/init.d/spring-app" gestartet werden "" /etc/init.d/spring-app stop "und andere Möglichkeiten wie Statusarbeit

Vermutlich, da die Skripte im init.d-Stil von springboot so aussehen, als hätten sie die erforderlichen magischen Zeichenfolgen (wie # Default-Start: 2 3 4 5), könnte chkconfig sie als "Dienst" hinzufügen.

Aber ich wollte, dass es mit systemd funktioniert

Damit dies funktioniert, habe ich viele der Rezepte in den anderen Antworten oben ausprobiert, aber keines davon funktionierte für mich unter Centos 7.2 mit Springboot 1.3. Meistens starteten sie den Dienst, konnten aber die PID nicht verfolgen

Am Ende stellte ich fest, dass Folgendes für mich funktioniert hat, als der Link /etc/init.d ebenfalls vorhanden war. Eine Datei ähnlich der folgenden sollte als installiert werden/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

Am Ende habe ich systemd service für das WAR / JAR-Layout ausgeführt

Ich rufe Java-Jar an, weil es flexibler ist. Ich habe auch versucht, ExecStart = spring-mvc.war zu setzen, aber obwohl es ausführbar ist, habe ich 'Exec-Formatfehler' erhalten.

Heutzutage ist systemd in allen Distributionen vorhanden und bietet eine gute Lösung zum Umleiten von Protokollen (syserr ist wichtig, wenn Ihr Dienst nicht einmal startet. Der Speicherort der log4j-Datei ist leer :)).

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 - Leitet die Syslog-Eingabe von der App in einen bestimmten Ordner / eine bestimmte Datei um

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 dieser Frage sollte die Antwort von @PbxMan Ihnen den Einstieg erleichtern:

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

Bearbeiten:

Es gibt eine andere, weniger gute Möglichkeit, einen Prozess beim Neustart mit cron zu starten:

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

Dies funktioniert, bietet Ihnen jedoch keine schöne Start / Stopp-Oberfläche für Ihre Anwendung. Du kannst es trotzdem einfach killmachen ...


Nicht wirklich, denn Spring Boot bietet dafür spezielle Funktionen.
Tristan

2

Ich kenne keine "Standard" -Methode in Schrumpffolie, um dies mit einer Java-App zu tun, aber es ist definitiv eine gute Idee (Sie möchten von den Keep-Alive- und Überwachungsfunktionen des Betriebssystems profitieren, wenn diese vorhanden sind). . Es ist auf der Roadmap, etwas von der Unterstützung des Spring Boot-Tools (Maven und Gradle) bereitzustellen, aber für den Moment müssen Sie wahrscheinlich Ihre eigenen rollen. Die beste Lösung, die ich derzeit kenne, ist Foreman , das einen deklarativen Ansatz und einzeilige Befehle zum Packen von Init-Skripten für verschiedene Standard-Betriebssystemformate (monit, sys V, upstart usw.) hat. Es gibt auch Hinweise darauf, dass Leute Sachen mit Gradle eingerichtet haben (z . B. hier ).


2

Benutzt du Maven? Dann sollten Sie das AppAssembler Plugin ausprobieren:

Das Application Assembler Plugin ist ein Maven-Plugin zum Generieren von Skripten zum Starten von Java-Anwendungen. ... Alle Artefakte (Abhängigkeiten + das Artefakt aus dem Projekt) werden dem Klassenpfad in den generierten Bin-Skripten hinzugefügt.

Unterstützte Plattformen:

Unix-Varianten

Windows NT (Windows 9x wird NICHT unterstützt)

Java Service Wrapper (JSW)

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


2

Die folgende Konfiguration ist in der Datei build.gradle in Spring Boot-Projekten erforderlich.

build.gradle

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

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

ausführbar = wahr

Dies ist erforderlich, um ein vollständig ausführbares JAR auf einem Unix-System (Centos und Ubuntu) zu erstellen.

Erstellen Sie eine .conf-Datei

Wenn Sie benutzerdefinierte JVM-Eigenschaften oder Ausführungsargumente für Spring Boot-Anwendungen konfigurieren möchten, können Sie eine .conf-Datei mit demselben Namen wie der Name der Spring Boot-Anwendung erstellen und parallel zur JAR-Datei platzieren.

Wenn Sie bedenken, dass your-app.jar der Name Ihrer Spring Boot-Anwendung ist, können Sie die folgende Datei erstellen.

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

Diese Konfiguration legt 64 MB RAM für die Spring Boot-Anwendung fest und aktiviert das Produktprofil.

Erstellen Sie einen neuen Benutzer unter Linux

Zur Erhöhung der Sicherheit müssen wir einen bestimmten Benutzer erstellen, um die Spring Boot-Anwendung als Dienst auszuführen.

Erstellen Sie einen neuen Benutzer

sudo useradd -s /sbin/nologin springboot

Ändern Sie unter Ubuntu / Debian den obigen Befehl wie folgt:

sudo useradd -s /usr/sbin/nologin springboot

Passwort festlegen

sudo passwd springboot

Machen Sie Springboot zum Besitzer der ausführbaren Datei

chown springboot:springboot your-app.jar

Verhindern Sie die Änderung der JAR-Datei

chmod 500 your-app.jar

Dadurch werden die Berechtigungen von jar so konfiguriert, dass es nicht geschrieben und nur von seinem Besitzer springboot gelesen oder ausgeführt werden kann.

Sie können Ihre JAR-Datei optional mit dem Befehl change attribute (chattr) als unveränderlich festlegen.

sudo chattr +i your-app.jar

Entsprechende Berechtigungen sollten auch für die entsprechende .conf-Datei festgelegt werden. .conf erfordert nur Lesezugriff (Octal 400) anstelle von Lese- und Ausführungszugriff (Octal 500)

chmod 400 your-app.conf

Erstellen Sie den Systemd-Dienst

/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

Starten Sie den Prozess automatisch neu, wenn er vom Betriebssystem beendet wird

Fügen Sie die beiden folgenden Attribute (Restart und RestartSec) hinzu, um den Prozess bei einem Fehler automatisch neu zu starten.

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

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

Durch die Änderung wird die Spring Boot-Anwendung im Fehlerfall mit einer Verzögerung von 30 Sekunden neu gestartet. Wenn Sie den Dienst mit dem Befehl systemctl beenden, wird kein Neustart durchgeführt.

Planen Sie den Service beim Systemstart

Verwenden Sie den folgenden Befehl, um die Anwendung so zu kennzeichnen, dass sie beim Systemstart automatisch gestartet wird:

Aktivieren Sie die Spring Boot-Anwendung beim Systemstart

sudo systemctl enable your-app.service

Starten Sie einen Stop the Service

systemctl kann in Ubuntu 16.04 LTS und 18.04 LTS verwendet werden, um den Prozess zu starten und zu stoppen.

Starten Sie den Prozess

sudo systemctl start your-app

Stoppen Sie den Prozess

sudo systemctl stop your-app

Verweise

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


1

Folgen Sie der hervorragenden Antwort von Chad, wenn Sie die Fehlermeldung "Fehler: Hauptklasse konnte nicht gefunden oder geladen werden" erhalten - und Sie verbringen ein paar Stunden damit, Fehler zu beheben, unabhängig davon, ob Sie ein Shell-Skript ausführen, das Ihre Java-App startet oder es startet von systemd selbst - und Sie wissen, dass Ihr Klassenpfad zu 100% korrekt ist, z. B. funktioniert das manuelle Ausführen des Shell-Skripts ebenso wie das Ausführen dessen, was Sie in systemd execstart haben. Stellen Sie sicher, dass Sie die Dinge als der richtige Benutzer ausführen! In meinem Fall hatte ich nach einiger Zeit der Fehlerbehebung verschiedene Benutzer ausprobiert - ich hatte endlich eine Ahnung, legte root als Benutzer - voila, die App wurde korrekt gestartet. Nachdem ich festgestellt habe, dass es sich um ein falsches Benutzerproblem handelt, habe ichchown -R user:user Der Ordner und die Unterordner sowie die App wurden korrekt als der angegebene Benutzer und die angegebene Gruppe ausgeführt, sodass sie nicht mehr als Root ausgeführt werden müssen (schlechte Sicherheit).


1

In systemd-Einheitendateien können Sie das Umgebungsvariablenverzeichnis oder über ein Verzeichnis festlegen EnvironmentFile. Ich würde vorschlagen, die Dinge so zu machen, da es die geringste Reibung zu sein scheint.

Beispieleinheitendatei

$ 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

Richten Sie dann eine Datei ein, /etc/sysconfig/hello-worlddie Großbuchstaben Ihrer Spring Boot-Variablen enthält. Beispielsweise server.portwürde eine aufgerufene Variable dem Formular SERVER_PORTals Umgebungsvariable folgen :

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

Der hier ausgenutzte Mechanismus besteht darin, dass Spring Boot-Anwendungen die Liste der Eigenschaften übernehmen und sie dann übersetzen, alles in Großbuchstaben schreiben und Punkte durch Unterstriche ersetzen. Sobald die Spring Boot-App diesen Prozess durchlaufen hat, sucht sie nach übereinstimmenden Umgebungsvariablen und verwendet alle gefundenen Variablen entsprechend.

Dies wird in dieser SO-Frage und Antwort mit dem Titel: Wie wird eine Spring Boot-Eigenschaft mit einem Unterstrich im Namen über Umgebungsvariablen ausführlicher hervorgehoben?

Verweise


1

Dies kann mit dem Systemd-Dienst in Ubuntu erfolgen

[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

Sie können diesem Link folgen, um eine ausführlichere Beschreibung und verschiedene Möglichkeiten zu erhalten. http://www.baeldung.com/spring-boot-app-as-a-service


1

Erstellen Sie ein Skript mit dem Namen your-app.service (rest-app.service). Wir sollten dieses Skript im Verzeichnis / etc / systemd / system ablegen. Hier ist der Beispielinhalt des Skripts

[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

Nächster:

 service rest-app start

Verweise

Geben Sie hier die Linkbeschreibung ein


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.