Aplikacja Spring Boot jako usługa

197

Jak ładnie skonfigurować aplikację Spring Boot spakowaną jako plik wykonywalny jako usługa w systemie Linux? Czy to zalecane podejście, czy powinienem przekonwertować tę aplikację na wojnę i zainstalować ją w Tomcat?

Obecnie mogę uruchomić aplikację Spring boot z screensesji, co jest miłe, ale wymaga ręcznego uruchomienia po ponownym uruchomieniu serwera.

Co szukam jest ogólne porady / kierunek lub przykładowy init.dscenariusz, jeśli moje podejście z wykonywalnego słoika jest właściwa.

Mariusz S.
źródło
Na początek, czy twoja dystrybucja używa upstart czy systemd?
yglodt

Odpowiedzi:

138

Następujące działa dla Springboot 1.3 i nowszych:

Jako usługa init.d

Plik wykonywalny ma zwykle komendy start, stop, restart i status. Skonfiguruje również plik PID w zwykłym katalogu / var / run i domyślnie zaloguje się w zwykłym katalogu / var / log.

Musisz tylko symlinkować słoik do /etc/init.d

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

LUB

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

Następnie możesz zrobić to, co zwykle

/etc/init.d/myapp start

Następnie skonfiguruj łącze na dowolnym poziomie uruchamiania, jeśli chcesz, aby aplikacja uruchamiała się / zatrzymywała podczas rozruchu, jeśli jest to pożądane.


Jako usługa systemowa

Aby uruchomić aplikację Spring Boot zainstalowaną w var / myapp, możesz dodać następujący skrypt w /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

Uwaga: jeśli używasz tej metody, nie zapomnij, aby sam plik jar był wykonywalny (z chmod + x), w przeciwnym razie wystąpi błąd z błędem „Odmowa zezwolenia”.

Odniesienie

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

Czad
źródło
1
Jak działa podejście „w pełni wykonywalnego JAR”? Używam CentOS 6.6. Dodałem <executable>true</executable>do mojego pom.xml, ale spakowany plik JAR nie wykonuje się (.... ./myapp.jar ... cannot execute binary file)
Abdull
5
Ta odpowiedź działa tylko w przypadku aktualnego kamienia milowego 1.3, który nie został jeszcze wydany. Oddziały 1.1 i 1.2 będą musiały sprawdzić inne odpowiedzi tutaj.
voor
6
Czy wiesz, jak przekazać argumenty wiosny, takie jak -Dspring.profiles.active=prodte usługi? Pytanie - stackoverflow.com/questions/31242291/…
nKognito
2
Nie jestem w stanie zatrzymać aplikacji Spring-Boot. /etc/init.d stopnie zatrzymuje aplikacji, próbuje ją uruchomić ponownie.
tintin
2
Jeśli chcesz monitorować proces i uruchomić go ponownie, jeśli umrze bez pisania demonów systemowych, sprawdź patrickgrimard.com/2014/06/06/…
ruX
112

Poniżej przedstawiono najprostszy sposób instalacji aplikacji Java jako usługi systemowej w systemie Linux.

Załóżmy, że używasz systemd(co obecnie robi każda współczesna dystrybucja):

Najpierw utwórz plik usługi o /etc/systemd/systemnazwie np. javaservice.serviceZ tą zawartością:

[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

Po drugie, powiadom systemdo nowym pliku usługi:

systemctl daemon-reload

i włącz go, aby działał podczas rozruchu:

systemctl enable javaservice.service

W końcu możesz użyć następujących poleceń, aby uruchomić / zatrzymać nową usługę:

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

Pod warunkiem, że używasz systemd, jest to najbardziej nieinwazyjny i czysty sposób na skonfigurowanie aplikacji Java jako usługi systemowej.

Szczególnie podoba mi się w tym rozwiązaniu to, że nie trzeba instalować ani konfigurować żadnego innego oprogramowania. Dostarczony systemdwykonuje całą pracę za Ciebie, a Twoja usługa zachowuje się jak każda inna usługa systemowa. Używam go od dłuższego czasu w produkcji, na różnych dystrybucjach i działa tak, jak można się spodziewać.

Kolejnym plusem jest to, że za pomocą /usr/bin/javamożna łatwo dodawać jvmparametry, takie jak -Xmx256m.

Przeczytaj także systemdczęść oficjalnej dokumentacji Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

yglodt
źródło
Niestety systemd nie jest dostępny dla
Centos
skąd wie, jak to zatrzymać? Nagrywa pid, a następnie go zabija?
mgła
2
Dzięki Spring Boot 1.3+ możesz wygenerować w pełni wykonywalny plik wojenny, więc nie potrzebujesz bitu java -jar ..., po prostu użyj tam nazwy pliku.
Pierre Henry,
1
Wolę używać pełnego wiersza polecenia Java, ponieważ w ten sposób można dodawać parametry JVM.
yglodt,
1
Dla prawidłowej sekwencji rozruchowej możesz dodawać wypowiedzi zamawiania do [Unit]sekcji, na przykład After=mysql.service, Before=apache2.service.
rustyx
57

Możesz także użyć supervisora, który jest bardzo przydatnym demonem, którego można użyć do łatwego kontrolowania usług. Usługi te są zdefiniowane przez proste pliki konfiguracyjne określające, co wykonać z którym użytkownikiem, w którym katalogu i tak dalej, istnieją opcje zillion. supervisord ma bardzo prostą składnię, więc stanowi bardzo dobrą alternatywę dla pisania skryptów inicjujących SysV.

Oto prosty supervisord plik konfiguracyjny dla programu, który próbujesz uruchomić / kontroli. (włóż to do /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

Aby kontrolować aplikację, musisz wykonać supervisorctl , który wyświetli monit, w którym możesz zacząć, zatrzymać, status swojej aplikacji.

CLI

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

Jeśli supervisorddemon już działa i dodałeś konfigurację dla swojego serwisu bez ponownego uruchamiania demona, możesz po prostu wykonać polecenie rereadi updatew supervisorctlpowłoce.

To naprawdę daje ci wszystkie elastyczne opcje, które miałbyś przy użyciu skryptów SysV Init, ale łatwe w użyciu i kontrolowaniu. Spójrz na dokumentację .

flazzarini
źródło
Wreszcie coś działało dla mnie od razu po wyjęciu z pudełka. Wielkie dzięki za podpowiedź superwizora.
Witalij Sazanowicz
Wykonuje to samo zadanie systemd, co wbudowane w większość obecnych dystrybucji Linuksa.
rustyx
18

Właśnie zacząłem to robić sam, więc do tej pory jestem pod względem skryptu kontrolera usługi init.d CentOS. Do tej pory działa całkiem nieźle, ale nie jestem hakerem Bash, więc jestem pewien, że jest miejsce na ulepszenia, więc myśli o ulepszeniu go są mile widziane.

Przede wszystkim mam krótki skrypt konfiguracyjny /data/svcmgmt/conf/my-spring-boot-api.shdla każdej usługi, który konfiguruje zmienne środowiskowe.

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

Korzystam z CentOS, więc aby upewnić się, że moje usługi zostaną uruchomione po ponownym uruchomieniu serwera, mam skrypt kontroli usługi w /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

Jak widać, wywołuje on skrypt początkowej konfiguracji, aby skonfigurować zmienne środowiskowe, a następnie wywołuje skrypt udostępniony, którego używam do ponownego uruchomienia wszystkich moich usług Spring Boot. Ten wspólny skrypt jest miejscem, w którym można znaleźć całe to wszystko:

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

Podczas zatrzymywania spróbuje użyć Spring Boot Actuator do wykonania kontrolowanego wyłączenia. Jednak w przypadku, gdy siłownik nie zostanie skonfigurowany lub nie zamknie się w rozsądnym czasie (daję mu 5 sekund, co jest naprawdę trochę krótkie), proces zostanie zabity.

Ponadto skrypt przyjmuje założenie, że proces Java uruchamiający aplikację będzie jedynym, który zawiera tekst „my-spring-boot-api.jar” w tekście szczegółów procesu. Jest to bezpieczne założenie w moim środowisku i oznacza, że ​​nie muszę śledzić PID.

Steve
źródło
3
Nie musisz pisać własnego skryptu start / stop. Jest to zapewniane od wersji Spring Boot 1.3 i nowszych. Więcej informacji można znaleźć w docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… .
gregturn,
Dobrze wiedzieć, że jest to opcja, ale jedyne, co robi, to eliminuje potrzebę wykonywania za pomocą java -jar. Reszta skryptu jest nadal potrzebna.
Steve,
Bardzo przydatne, gdy /etc/init.d lub systemd nie jest opcją, dzięki za udostępnienie.
bernardn,
@ Steve: Nie. Wymyślasz koło na nowo. Aha, i teraz mamy system.
Martin Schröder,
Kiedy potrzebujesz przekazać parametry do JVM (jak -javaagent lub -D parametry), jest to unikalny sposób, tks @Steve!
Dyorgio
14

Jeśli chcesz używać Spring Boot 1.2.5 z Spring Boot Maven Plugin 1.3.0.M2, oto nasze rozwiązanie:

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

Następnie skompiluj jako ususal: mvn clean packageutwórz dowiązanie symboliczne ln -s /.../myapp.jar /etc/init.d/myapp, chmod +x /etc/init.d/myappuruchom go i uruchom service myapp start(z Ubuntu Server)

Benjamin M.
źródło
co z uruchomionymi plikami WAR? nie działa dla mnie z układem WAR.
Radu Toader
Co ciekawe, działa to z wydaniem 1.3.0.M2, ale przy próbie dostałem błąd 1.3.0.RC1.
JBCP
Masz pomysł, jak to zrobić z gradem zamiast z maven?
Geir,
Podczas korzystania z Gradle, ta konfiguracja jest wykonywana przy użyciu springBoot { executable = true }bloku.
Natix
@RaduToader: Czy byłeś w stanie wykonać plik WAR jako usługę?
naveenkumarbv
9

Wiem, że to starsze pytanie, ale chciałem przedstawić jeszcze jeden sposób, jakim jest plugin appassembler-maven-plug . Oto odpowiednia część z mojej POM, która zawiera wiele dodatkowych wartości opcji, które uznaliśmy za przydatne:

<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
źródło
6

JAKO USŁUGA WINDOWS

Jeśli chcesz, aby działało to w systemie Windows, pobierz plik winsw.exe z

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

Następnie zmień nazwę pliku na jar (np. Twoja aplikacja .jar)

winsw.exe -> your-app.exe

Teraz utwórz plik xml twoja-app.xml i skopiuj do niego następującą treść

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

Upewnij się, że exe i xml wraz ze słoikiem w tym samym folderze.

Po otwarciu wiersza polecenia w Administratorze uprzedzić i zainstalować go w usłudze systemu Windows.

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

Jeśli to się nie powiedzie

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

Następnie spróbuj wykonać następujące czynności:

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

Otóż ​​to :) .

Aby odinstalować usługę w systemie Windows

your-app.exe uninstall

Aby zobaczyć / uruchomić / zatrzymać usługę: win + r i wpisz Narzędzia administracyjne, a następnie wybierz usługę z tego. Następnie kliknij prawym przyciskiem myszy wybierz opcję - uruchom / zatrzymaj

Arundev
źródło
Wykonałem te same kroki, aby uruchomić słoik rozruchu wiosennego jak usługa Windows w intranetowej firmie env, ale usługa się nie podnosi. Pojawia się okno z błędem: Błąd: 1067 Proces został nieoczekiwanie zakończony. Czy mógłbyś pomóc lub zasugerować, co należy zrobić?
Nikhil Singh Bhadoriya
Czy masz na to pozwolenie? Jeśli jesteś administratorem, nie spowoduje to żadnych problemów. Czy możesz sprawdzić, czy masz uprawnienia administratora.
Arundev
stackoverflow.com/questions/18205111/... czy możesz spróbować, może to pomóc w rozwiązaniu problemu.
Arundev
dzięki za szybką odpowiedź. Uruchomiłem usługę, rozwiązując problem ze znacznikiem w pliku xml.
Nikhil Singh Bhadoriya
4

Mój skrypt SysVInit dla Centos 6 / RHEL (jeszcze nie idealny). Ten skrypt wymaga ApplicationPidListener .

Źródło /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 $?

Przykładowy plik konfiguracyjny /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
Mariusz S.
źródło
4

Oto skrypt, który wdraża wykonywalny jar jako usługę systemową.

Tworzy użytkownika dla usługi i pliku .service, umieszcza plik jar w katalogu / var i dokonuje podstawowej blokady uprawnień.

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

Przykład: wprowadź opis zdjęcia tutaj

Użytkownik0
źródło
4

Próbuję utworzyć aplikacje Springboot, które są prezentowane jako skrypt powłoki w stylu „init.d” ze skompresowaną aplikacją Java na końcu

Poprzez symlinkowanie tych skryptów z /etc/init.d/spring-app do /opt/spring-app.jar i chmod'ing jar, aby był wykonywalny, możliwe jest uruchomienie "/etc/init.d/spring-app „” /etc/init.d/spring-app stop ”i inne możliwości, takie jak praca statusu

Przypuszczalnie skoro skrypty w stylu init.d z springboot wyglądają, że mają niezbędne magiczne łańcuchy (jak # Default-Start: 2 3 4 5 ), chkconfig mógłby dodać je jako „usługę”

Ale chciałem, aby działało z systememd

Aby to zadziałało, wypróbowałem wiele przepisów z innych powyższych odpowiedzi, ale żadna z nich nie działała dla mnie w Centos 7.2 z Springboot 1.3. W większości uruchomiliby usługę, ale nie byli w stanie śledzić pid

W końcu okazało się, że następujące działało dla mnie, kiedy również istniał link /etc/init.d. Plik podobny do poniższego powinien zostać zainstalowany jako/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
źródło
4

Skończyło się na usłudze systemowej dla układu WAR / JAR

Nazywam java -jar, ponieważ jest bardziej elastyczny. Próbowałem również umieścić ExecStart = spring-mvc.war, ale mimo że jest wykonywalny, dostałem „Błąd formatu Exec”

W każdym razie systemd jest obecny na wszystkich dystrybucjach i oferuje dobre rozwiązanie do przekierowywania dzienników (syserr jest ważny, gdy usługa nawet się nie uruchamia, lokalizacja pliku log4j będzie pusta :)).

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 - przekieruj dane wejściowe syslog z aplikacji do określonego folderu / pliku

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
źródło
3

W tym pytaniu odpowiedź od @PbxMan powinna zacząć:

Uruchom aplikację Java jako usługę w systemie Linux

Edytować:

Istnieje inny, mniej przyjemny sposób na uruchomienie procesu przy ponownym uruchomieniu, za pomocą crona:

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

Działa to, ale nie zapewnia przyjemnego interfejsu start / stop dla twojej aplikacji. W killkażdym razie możesz po prostu to po prostu …

yglodt
źródło
Nie bardzo, ponieważ Spring Boot oferuje specjalne funkcje, aby to zrobić.
Tristan
2

Nie znam „standardowego” sposobu, w jaki można to zrobić za pomocą aplikacji Java, ale zdecydowanie jest to dobry pomysł (jeśli chcesz skorzystać z możliwości utrzymania i monitorowania systemu operacyjnego, jeśli są dostępne) . W planie jest dostarczenie czegoś z obsługi narzędzia Spring Boot (maven i gradle), ale na razie prawdopodobnie będziesz musiał rzucić własne. Najlepszym rozwiązaniem, jakie znam obecnie, jest Foreman , który ma deklaratywne podejście i jednowierszowe polecenia do pakowania skryptów inicjujących dla różnych standardowych formatów systemu operacyjnego (monitor, sys V, upstart itp.). Istnieją również dowody na to, że ludzie ustawiali różne stopnie (np. Tutaj ).

Dave Syer
źródło
2

Czy używasz Maven? Następnie powinieneś wypróbować wtyczkę AppAssembler:

Wtyczka Application Assembler to wtyczka Maven do generowania skryptów do uruchamiania aplikacji Java. ... Wszystkie artefakty (zależności + artefakt z projektu) są dodawane do ścieżki klas w wygenerowanych skryptach bin.

Obsługiwane platformy:

Warianty Unix

Windows NT (Windows 9x NIE jest obsługiwany)

Java Service Wrapper (JSW)

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

d0x
źródło
2

Następująca konfiguracja jest wymagana w pliku build.gradle w projektach Spring Boot.

build.gradle

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

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

plik wykonywalny = prawda

Jest to wymagane do utworzenia w pełni wykonywalnego jar w systemie Unix (Centos i Ubuntu)

Utwórz plik .conf

Jeśli chcesz skonfigurować niestandardowe właściwości JVM lub argumenty uruchamiania aplikacji Spring Boot, możesz utworzyć plik .conf o tej samej nazwie co nazwa aplikacji Spring Boot i umieścić go równolegle do pliku jar.

Biorąc pod uwagę, że twoja-app.jar jest nazwą twojej aplikacji Spring Boot, możesz utworzyć następujący plik.

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

Ta konfiguracja ustawi 64 MB pamięci RAM dla aplikacji Spring Boot i aktywuje profil prod.

Utwórz nowego użytkownika w systemie Linux

Aby zwiększyć bezpieczeństwo, musimy utworzyć konkretnego użytkownika, aby uruchomić aplikację Spring Boot jako usługę.

Utwórz nowego użytkownika

sudo useradd -s /sbin/nologin springboot

W systemie Ubuntu / Debian zmodyfikuj powyższe polecenie w następujący sposób:

sudo useradd -s /usr/sbin/nologin springboot

Ustaw hasło

sudo passwd springboot

Ustaw Springboot właścicielem pliku wykonywalnego

chown springboot:springboot your-app.jar

Zapobiegaj modyfikacji pliku jar

chmod 500 your-app.jar

Spowoduje to skonfigurowanie uprawnień jar tak, że nie będzie można go zapisać i będzie można go odczytać lub wykonać tylko przez springboot właściciela.

Opcjonalnie możesz ustawić plik jar jako niezmienny za pomocą polecenia zmiany atrybutu (chattr).

sudo chattr +i your-app.jar

Należy również ustawić odpowiednie uprawnienia dla odpowiedniego pliku .conf. .conf wymaga tylko dostępu do odczytu (Octal 400) zamiast dostępu do odczytu + wykonania (Octal 500)

chmod 400 your-app.conf

Utwórz usługę 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

Automatycznie uruchom ponownie proces, jeśli zostanie zabity przez system operacyjny

Dodaj poniższe dwa atrybuty (Restart i RestartSec), aby automatycznie ponownie uruchomić proces w przypadku awarii.

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

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

Zmiana spowoduje ponowne uruchomienie aplikacji Spring Boot w przypadku awarii z opóźnieniem 30 sekund. Jeśli zatrzymasz usługę za pomocą polecenia systemctl, ponowne uruchomienie nie nastąpi.

Zaplanuj usługę przy uruchomieniu systemu

Aby oflagować aplikację, aby uruchamiała się automatycznie podczas rozruchu systemu, użyj następującego polecenia:

Włącz aplikację Spring Boot podczas uruchamiania systemu

sudo systemctl enable your-app.service

Uruchom usługę Zatrzymaj usługę

Systemctl może być używany w Ubuntu 16.04 LTS i 18.04 LTS do uruchamiania i zatrzymywania procesu.

Rozpocznij proces

sudo systemctl start your-app

Zatrzymaj proces

sudo systemctl stop your-app

Bibliografia

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

ismael
źródło
1

Po otrzymaniu doskonałej odpowiedzi Chada, jeśli pojawi się błąd „Błąd: nie można znaleźć lub załadować klasy głównej” - i poświęcasz kilka godzin na próby rozwiązania tego problemu, niezależnie od tego, czy wykonujesz skrypt powłoki, który uruchamia aplikację Java, czy ją uruchamia z samego systemd - i wiesz, że twoja ścieżka klasy jest w 100% poprawna, np. ręczne uruchamianie skryptu powłoki działa tak samo, jak uruchamianie tego, co masz w systemst execart. Upewnij się, że działasz jako właściwy użytkownik! W moim przypadku próbowałem różnych użytkowników, po dłuższym czasie rozwiązywania problemów - w końcu miałem przeczucie, ustawiłem root jako użytkownik - voila, aplikacja uruchomiła się poprawnie. Po ustaleniu, że to zły problem dla użytkownika, jachown -R user:user że folder i podfoldery oraz aplikacja działały poprawnie jako określony użytkownik i grupa, więc nie trzeba już uruchamiać go jako root (złe bezpieczeństwo).

JGlass
źródło
1

W plikach jednostek systemowych możesz ustawić katalog zmiennych środowiskowych lub poprzez EnvironmentFile. Proponuję robić to w ten sposób, ponieważ wydaje się, że jest to najmniej tarcie.

Przykładowy plik jednostki

$ 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

Następnie skonfiguruj plik, pod /etc/sysconfig/hello-worldktórym znajdują się wielkie litery zmiennych Spring Boot. Na przykład zmienna o nazwie server.portbędzie miała postać SERVER_PORTzmiennej środowiskowej:

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

Mechanizm wykorzystywany tutaj polega na tym, że aplikacje Spring Boot biorą listę właściwości, a następnie tłumaczą je, robiąc wszystko dużymi literami i zamieniając kropki na podkreślenia. Gdy aplikacja Spring Boot przejdzie ten proces, następnie szuka pasujących zmiennych środowiskowych i odpowiednio wykorzystuje znalezione zmienne.

Zostało to bardziej szczegółowo uwypuklone w tym pytaniu SO zatytułowanym: Jak ustawić właściwość Spring Boot ze znakiem podkreślenia w jej nazwie poprzez Zmienne środowiskowe?

Bibliografia

slm
źródło
1

Można to zrobić za pomocą usługi Systemd w 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

Możesz skorzystać z tego linku, aby uzyskać bardziej szczegółowy opis i różne sposoby na zrobienie tego. http://www.baeldung.com/spring-boot-app-as-a-service

Mujeeb Rahman
źródło
1

Utwórz skrypt o nazwie twoja-app.service (rest-app.service). Powinniśmy umieścić ten skrypt w katalogu / etc / systemd / system. Oto przykładowa zawartość skryptu

[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

Kolejny:

 service rest-app start

Bibliografia

wprowadź opis linku tutaj

ismael
źródło
Wygląda tak samo -> stackoverflow.com/a/30497095/516167
MariuszS