Aplicación Spring Boot como servicio

197

¿Cómo configurar bien la aplicación Spring Boot empaquetada como jar ejecutable como un Servicio en un sistema Linux? ¿Es este enfoque recomendado o debería convertir esta aplicación a war e instalarla en Tomcat?

Actualmente puedo ejecutar la aplicación de arranque Spring desde la screensesión, lo que es bueno, pero requiere un inicio manual después del reinicio del servidor.

Lo que estoy buscando es asesoramiento general / dirección o init.dscript de muestra , si mi enfoque con jar ejecutable es correcto.

MariuszS
fuente
Para comenzar, ¿utiliza su distribución upstart o systemd?
yglodt

Respuestas:

138

Lo siguiente funciona para springboot 1.3 y superior:

Como servicio init.d

El jar ejecutable tiene los comandos habituales de inicio, detención, reinicio y estado. También configurará un archivo PID en el directorio habitual / var / run e iniciará sesión en el directorio habitual / var / log de forma predeterminada.

Solo necesita vincular su jar en /etc/init.d así

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

O

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

Después de eso puedes hacer lo habitual

/etc/init.d/myapp start

Luego, configure un enlace en el nivel de ejecución en el que desee que la aplicación se inicie / pare en el arranque si así lo desea.


Como un servicio systemd

Para ejecutar una aplicación Spring Boot instalada en var / myapp, puede agregar el siguiente script en /etc/systemd/system/myapp.service:

[Unit]
Description=myapp
After=syslog.target

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

[Install]
WantedBy=multi-user.target

NB: en caso de que esté utilizando este método, no olvide hacer que el archivo jar sea ejecutable (con chmod + x) de lo contrario fallará con el error "Permiso denegado".

Referencia

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

Chad
fuente
1
¿Cómo funciona el enfoque "JAR totalmente ejecutable"? Yo uso CentOS 6.6. He añadido <executable>true</executable>a mi pom.xml, pero el archivo JAR envasados no ejecuta (... ./myapp.jar ... cannot execute binary file.)
Abdull
55
Esta respuesta solo funciona para el 1.3 Milestone actual, que aún no se ha lanzado. Las sucursales 1.1 y 1.2 deberán verificar las otras respuestas aquí.
voor
66
¿Conocen a los chicos cómo pasar los argumentos de la primavera, como -Dspring.profiles.active=proda estos servicios? Pregunta - stackoverflow.com/questions/31242291/…
nKognito
2
No puedo detener la aplicación spring-boot. /etc/init.d stopno está deteniendo la aplicación, está intentando iniciarla nuevamente.
tintin
2
Si desea monitorear el proceso y reiniciarlo si muere sin escribir demonios del sistema, visite patrickgrimard.com/2014/06/06/…
ruX
112

Lo que sigue es la forma más fácil de instalar una aplicación Java como servicio del sistema en Linux.

Supongamos que está utilizando systemd(lo que cualquier distribución moderna hace hoy en día):

En primer lugar, cree un archivo de servicio en /etc/systemd/system nombre, por ejemplo, javaservice.servicecon este contenido:

[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

En segundo lugar, notificar systemd el nuevo archivo de servicio:

systemctl daemon-reload

y habilitarlo, para que se ejecute en el arranque:

systemctl enable javaservice.service

Eventualmente, puede usar los siguientes comandos para iniciar / detener su nuevo servicio:

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

Siempre que estés usando systemd , esta es la forma más no intrusiva y limpia de configurar una aplicación Java como servicio del sistema.

Lo que me gusta especialmente de esta solución es el hecho de que no necesita instalar y configurar ningún otro software. El enviadosystemd hace todo el trabajo por usted y su servicio se comporta como cualquier otro servicio del sistema. Lo uso en producción desde hace un tiempo, en diferentes distribuciones, y funciona como es de esperar.

Otra ventaja es que, al usar /usr/bin/java, puede agregar fácilmentejvm parámetros como -Xmx256m.

Lea también la systemdparte en la documentación oficial de Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

yglodt
fuente
Lamentablemente, systemd no está disponible para Centos 6
MariuszS
¿Cómo sabe cómo detenerlo? Graba el pid y luego lo mata?
niebla
2
Con Spring Boot 1.3+ puedes generar un archivo war totalmente ejecutable, así que no necesitas el bit java -jar ... solo usa el nombre del archivo allí.
Pierre Henry
1
Prefiero usar la línea de comandos completa de Java porque de esa manera puedes agregar parámetros jvm.
yglodt
1
Para una secuencia de arranque apropiado es posible que desee agregar instrucciones de pedido a la [Unit]sección, por ejemplo After=mysql.service, Before=apache2.service.
rustyx
57

También podría usar supervisor, que es un demonio muy útil, que puede usarse para controlar fácilmente los servicios. Estos servicios se definen mediante simples archivos de configuración que definen qué ejecutar con qué usuario en qué directorio, etc., hay un montón de opciones. supervisord tiene una sintaxis muy simple, por lo que es una muy buena alternativa para escribir scripts de inicio SysV.

Aquí hay un archivo de configuración de supervisor simple para el programa que está intentando ejecutar / controlar. (poner esto en /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

Para controlar la aplicación, necesitará ejecutar supervisorctl , que le presentará un mensaje donde puede iniciar, detener y el estado de su aplicación.

CLI

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

Si el supervisorddemonio ya se está ejecutando y que ha añadido la configuración para su serivce sin necesidad de reiniciar el demonio que puede hacer un simple reready updatecomando en elsupervisorctl shell.

Esto realmente le brinda todas las flexibilidades que tendría utilizando los scripts de SysV Init, pero fáciles de usar y controlar. Echa un vistazo a la documentación .

flazzarini
fuente
Finalmente, algo me funcionó de inmediato. Muchas gracias por la pista del supervisor.
Vitaly Sazanovich
Esto hace el mismo trabajo que systemd, que está integrado en la mayoría de las distribuciones de Linux actuales.
rustyx
18

Acabo de hacer esto yo mismo, así que lo siguiente es donde estoy hasta ahora en términos de un script de controlador de servicio CentOS init.d. Hasta ahora está funcionando bastante bien, pero no soy un hacker de Bash, así que estoy seguro de que hay margen de mejora, por lo que las ideas para mejorarlo son bienvenidas.

En primer lugar, tengo un script de configuración corto /data/svcmgmt/conf/my-spring-boot-api.shpara cada servicio, que configura las variables de entorno.

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

Estoy usando CentOS, por lo que para garantizar que mis servicios se inicien después de reiniciar el servidor, tengo un script de control de servicio en /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

Como puede ver, eso llama al script de configuración inicial para configurar variables de entorno y luego llama a un script compartido que uso para reiniciar todos mis servicios Spring Boot. Ese script compartido es donde se puede encontrar la esencia de todo:

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

Al detenerse, intentará usar el actuador Spring Boot para realizar un apagado controlado. Sin embargo, en caso de que el Actuador no esté configurado o no se apague dentro de un período de tiempo razonable (le doy 5 segundos, lo cual es un poco corto en realidad), el proceso se cancelará.

Además, el script supone que el proceso de Java que ejecuta la aplicación será el único con "my-spring-boot-api.jar" en el texto de los detalles del proceso. Esta es una suposición segura en mi entorno y significa que no necesito hacer un seguimiento de los PID.

Steve
fuente
3
No es necesario escribir su propio guión de inicio / detención. Esto se proporciona a partir de Spring Boot 1.3 y posteriores. Ver docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… para más detalles.
gregturn
Es bueno saber que es una opción, pero todo lo que hace es eliminar la necesidad de ejecutar usando java -jar. El resto del guión todavía es necesario.
Steve
Muy útil para cuando /etc/init.d o systemd no es una opción, gracias por compartir.
bernardn
@ Steve: No. Estás reinventando la rueda. Ah, y tenemos systemd ahora.
Martin Schröder
Cuando necesite pasar parámetros a JVM (como los parámetros -javaagent o -D), esta es la forma única, ¡tks @Steve!
Dyorgio
14

Si desea usar Spring Boot 1.2.5 con Spring Boot Maven Plugin 1.3.0.M2, aquí está nuestra solución:

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

Luego compile como ususal: mvn clean packagehaga un enlace simbólico ln -s /.../myapp.jar /etc/init.d/myapp, hágalo ejecutable chmod +x /etc/init.d/myappe inícielo service myapp start(con Ubuntu Server)

Benjamin M
fuente
¿Qué pasa con los archivos WAR ejecutables? no me funciona con el diseño WAR.
Radu Toader
Curiosamente, esto funciona con el lanzamiento 1.3.0.M2, pero recibí un error cuando lo intenté 1.3.0.RC1.
JBCP
¿Alguna idea de cómo hacer esto con gradle en lugar de maven?
Geir
Cuando se usa Gradle, esta configuración se realiza usando springBoot { executable = true }block.
Natix
@RaduToader: ¿Pudiste ejecutar el archivo WAR como servicio?
naveenkumarbv
9

Sé que esta es una pregunta anterior, pero quería presentar otra forma más, que es el complemento appassembler-maven-plugin . Aquí está la parte relevante de mi POM que incluye muchos valores de opciones adicionales que encontramos útiles:

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

COMO SERVICIO DE VENTANAS

Si desea que esto se ejecute en la máquina de Windows, descargue el winsw.exe de

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

Después de eso, cámbiele el nombre a nombre de archivo jar (por ejemplo: your-app .jar)

winsw.exe -> your-app.exe

Ahora cree un archivo xml your-app.xml y copie el siguiente contenido

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

Asegúrese de que el exe y xml junto con jar en una misma carpeta.

Después de este símbolo del sistema abierto en el administrador anterior e instalarlo en el servicio de Windows.

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

Si falla con

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

Luego intente lo siguiente:

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

Eso es :) .

Para desinstalar el servicio en windows

your-app.exe uninstall

Para ver / ejecutar / detener el servicio: win + r y escriba Herramientas administrativas, luego seleccione el servicio de eso. Luego, haga clic con el botón derecho en la opción: ejecutar / detener

Arundev
fuente
He seguido los mismos pasos para ejecutar Spring Jar Jar como servicio de Windows en el entorno de intranet de la empresa, pero el servicio no se está poniendo en marcha. Aparece una ventana con error: Error: 1067 El proceso finalizó inesperadamente ¿Podría ayudarme o sugerirme qué debe hacerse?
Nikhil Singh Bhadoriya
¿Tienes todo el permiso para hacer eso? Si es administrador, esto no causará ningún problema. ¿Puede verificar que tiene derechos de administrador?
Arundev
stackoverflow.com/questions/18205111/… ¿ puede intentarlo? Esto puede ayudarlo a resolver el problema.
Arundev
gracias por la rápida respuesta, puse en funcionamiento mi servicio al corregir un problema con la etiqueta en el archivo xml.
Nikhil Singh Bhadoriya
4

Mi script SysVInit para Centos 6 / RHEL (todavía no es ideal). Este script requiere ApplicationPidListener .

Fuente de /etc/init.d/app

#!/bin/sh
#
# app Spring Boot Application 
#
# chkconfig:   345 20 80
# description: App Service
#           

### BEGIN INIT INFO
# Provides: App
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 3 4 5 
# Default-Stop: 0 1 2 6
# Short-Description: Application
# Description:      
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

exec="/usr/bin/java"
prog="app"
app_home=/home/$prog/
user=$prog

[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog

lockfile=/var/lock/subsys/$prog    
pid=$app_home/$prog.pid

start() {

    [ -x $exec ] || exit 5
    [ -f $config ] || exit 6
    # Check that networking is up.
    [ "$NETWORKING" = "no" ] && exit 1
    echo -n $"Starting $prog: "
    cd $app_home
    daemon --check $prog --pidfile $pid --user $user $exec $app_args &
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc -p $pid $prog
    retval=$?
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    restart
}

force_reload() {
    restart
}

rh_status() {
    status -p $pid $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
exit $?

Archivo de configuración de muestra /etc/sysconfig/app:

exec=/opt/jdk1.8.0_05/jre/bin/java

user=myuser
app_home=/home/mysuer/

app_args="-jar app.jar"

pid=$app_home/app.pid
MariuszS
fuente
4

Aquí hay un script que implementa un jar ejecutable como un servicio systemd.

Crea un usuario para el servicio y el archivo .service, y coloca el archivo jar en / var, y realiza un bloqueo básico de privilegios.

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

Ejemplo: ingrese la descripción de la imagen aquí

Usuario0
fuente
4

Estoy tratando de hacer aplicaciones Springboot que se presentan como un script de shell de estilo "init.d" con una aplicación Java comprimida añadida al final

Al vincular estos scripts de /etc/init.d/spring-app a /opt/spring-app.jar y modificar el jar para que sea ejecutable, es posible hacer que "/etc/init.d/spring-app start "" /etc/init.d/spring-app stop "y otras posibilidades como el trabajo de estado

Presumiblemente, como las secuencias de comandos de estilo init.d de springboot parecen tener las necesarias cadenas mágicas (como # Default-Start: 2 3 4 5 ) chkconfig podría agregarlo como un "servicio"

Pero quería que funcionara con systemd

Para que esto funcione, probé muchas de las respuestas en las otras respuestas anteriores, pero ninguna de ellas funcionó para mí. en Centos 7.2 con Springboot 1.3. Principalmente iniciarían el servicio pero no podrían rastrear el pid

Al final, descubrí que lo siguiente funcionó para mí, cuando el enlace /etc/init.d también estaba en su lugar. Un archivo similar al siguiente se debe instalar como/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
fuente
4

Terminé haciendo el servicio systemd para el diseño WAR / JAR

Llamo a java -jar porque es más flexible. Intenté también poner ExecStart = spring-mvc.war pero aunque es ejecutable, recibí 'Error de formato de Exec'

De todos modos en estos días, systemd está presente en todas las distribuciones, y ofrece una buena solución para redirigir los registros (syserr es importante cuando su servicio ni siquiera inicia, la ubicación del archivo log4j estará vacía :)).

cat /etc/systemd/system/spring-mvc.service 
[Unit]
Description=Spring MVC Java Service

[Service]
User=spring-mvc
# The configuration file application.properties should be here:
WorkingDirectory=/usr/local/spring-mvc


# Run ExecStartPre with root-permissions
PermissionsStartOnly=true

ExecStartPre=-/bin/mkdir -p /var/log/spring-mvc


ExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc
ExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc



#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
ExecStart=/usr/bin/java \
        -Dlog4j.configurationFile=log4j2-spring.xml \
        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \
        -Dspring.profiles.active=dev \
        -Denvironment-type=dev \
        -XX:+UseConcMarkSweepGC \
        -XX:CMSInitiatingOccupancyFraction=80 \
        -XX:NewSize=756m \
        -XX:MetaspaceSize=256m \
        -Dsun.net.inetaddr.ttl=5 \
        -Xloggc:/var/log/spring-mvc/gc.log \
        -verbose:gc \
        -verbosegc \
        -XX:+DisableExplicitGC \
        -XX:+PrintGCDetails \
        -XX:+PrintGCDateStamps \
        -XX:+PreserveFramePointer \
        -XX:+StartAttachListener \
        -Xms1024m \
        -Xmx1024m \
        -XX:+HeapDumpOnOutOfMemoryError \
        -jar spring-mvc.war

SuccessExitStatus=143
StandardOutput=journal
StandardError=journal


KillSignal=SIGINT
TimeoutStopSec=20
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=10

LimitNOFILE=500000
LimitNPROC=500000

#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=
#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=¶

SyslogIdentifier=spring-mvc

[Install]
WantedBy=multi-user.target


# https://www.freedesktop.org/software/systemd/man/journalctl.html
#check logs --- journalctl -u spring-mvc -f -o cat

rsyslog: redirige la entrada de syslog de la aplicación a una carpeta / archivo específico

cat /etc/rsyslog.d/30-spring-mvc.conf 
if $programname == 'spring-mvc' then /var/log/spring-mvc/spring-mvc.log
& stop

rotar

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

En esta pregunta, la respuesta de @PbxMan debería ayudarlo a comenzar:

Ejecute una aplicación Java como servicio en Linux

Editar:

Hay otra forma menos agradable de comenzar un proceso al reiniciar, usando cron:

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

Esto funciona, pero no ofrece una interfaz agradable de inicio / detención para su aplicación. Todavía puedes simplemente killhacerlo de todos modos ...

yglodt
fuente
En realidad no, porque Spring Boot ofrece características especiales para hacer esto.
Tristan
2

No conozco una forma "estándar" de reducir la forma de hacer eso con una aplicación Java, pero definitivamente es una buena idea (si quieres, puedes beneficiarte de las capacidades de mantenimiento y monitoreo del sistema operativo). . Está en la hoja de ruta para proporcionar algo del soporte de la herramienta Spring Boot (maven y gradle), pero por ahora probablemente tendrá que rodar la suya. La mejor solución que conozco en este momento es Foreman , que tiene un enfoque declarativo y comandos de una línea para empaquetar scripts de inicio para varios formatos estándar del sistema operativo (monit, sys V, upstart, etc.). También hay evidencia de personas que han configurado cosas con gradle (por ejemplo, aquí ).

Dave Syer
fuente
2

¿Estás usando Maven? Entonces deberías probar el complemento AppAssembler:

Application Assembler Plugin es un complemento de Maven para generar scripts para iniciar aplicaciones java. ... Todos los artefactos (dependencias + el artefacto del proyecto) se agregan al classpath en los scripts de bin generados.

Plataformas soportadas:

Variantes Unix

Windows NT (Windows 9x NO es compatible)

Java Service Wrapper (JSW)

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

d0x
fuente
2

Se requiere la siguiente configuración en el archivo build.gradle en los proyectos Spring Boot.

build.gradle

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

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

ejecutable = verdadero

Esto es necesario para hacer un jar totalmente ejecutable en un sistema Unix (Centos y Ubuntu)

Crear un archivo .conf

Si desea configurar propiedades JVM personalizadas o argumentos de ejecución de la aplicación Spring Boot, puede crear un archivo .conf con el mismo nombre que el nombre de la aplicación Spring Boot y colocarlo en paralelo al archivo jar.

Teniendo en cuenta que your-app.jar es el nombre de su aplicación Spring Boot, puede crear el siguiente archivo.

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

Esta configuración establecerá 64 MB de RAM para la aplicación Spring Boot y activará el perfil de producción.

Crea un nuevo usuario en Linux

Para mejorar la seguridad, debemos crear un usuario específico para ejecutar la aplicación Spring Boot como servicio.

Crea un nuevo usuario

sudo useradd -s /sbin/nologin springboot

En Ubuntu / Debian, modifique el comando anterior de la siguiente manera:

sudo useradd -s /usr/sbin/nologin springboot

Configurar la clave

sudo passwd springboot

Hacer que springboot sea el propietario del archivo ejecutable

chown springboot:springboot your-app.jar

Prevenir la modificación del archivo jar

chmod 500 your-app.jar

Esto configurará los permisos de jar para que no pueda escribirse y solo pueda leerlo o ejecutarlo su springboot propietario.

Opcionalmente, puede hacer que su archivo jar sea inmutable utilizando el comando change attribute (chattr).

sudo chattr +i your-app.jar

También se deben establecer los permisos apropiados para el archivo .conf correspondiente. .conf requiere solo acceso de lectura (Octal 400) en lugar de acceso de lectura + ejecución (Octal 500)

chmod 400 your-app.conf

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

Reiniciar automáticamente el proceso si el sistema operativo lo mata

Agregue los dos atributos a continuación (Reiniciar y ReiniciarSec) para reiniciar automáticamente el proceso en caso de falla.

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

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

El cambio hará que la aplicación Spring Boot se reinicie en caso de falla con un retraso de 30 segundos. Si detiene el servicio utilizando el comando systemctl, no se reiniciará.

Programar servicio al inicio del sistema

Para marcar la aplicación para que se inicie automáticamente en el arranque del sistema, use el siguiente comando:

Habilitar la aplicación Spring Boot al iniciar el sistema

sudo systemctl enable your-app.service

Comience y detenga el servicio

systemctl se puede usar en Ubuntu 16.04 LTS y 18.04 LTS para iniciar y detener el proceso.

Iniciar el proceso

sudo systemctl start your-app

Detener el proceso

sudo systemctl stop your-app

Referencias

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

ismael
fuente
1

Continuando con la excelente respuesta de Chad, si obtiene un error de "Error: no se pudo encontrar o cargar la clase principal" , y pasa un par de horas tratando de solucionarlo, ya sea que esté ejecutando un script de shell que inicia su aplicación Java o lo inicia del sistema en sí, y usted sabe que su classpath es 100% correcto, por ejemplo, ejecutar manualmente el script de shell funciona tan bien como lo que tiene en systemd execstart. Asegúrese de que ejecutar las cosas como el usuario correcto! En mi caso, había intentado con diferentes usuarios, después de un buen tiempo de resolución de problemas, finalmente tuve el presentimiento, puse root como usuario, es decir, la aplicación comenzó correctamente. Después de determinar que era un problema de usuario incorrecto, yochown -R user:user la carpeta y las subcarpetas y la aplicación se ejecutaron correctamente como el usuario y el grupo especificados, por lo que ya no es necesario ejecutarlo como root (mala seguridad).

JGlass
fuente
1

En los archivos de la unidad systemd puede establecer el directorio de variables de entorno o mediante un EnvironmentFile. Propondría hacer las cosas de esta manera, ya que parece ser la menor cantidad de fricción.

Archivo de unidad de muestra

$ 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

Luego, configure un archivo con los /etc/sysconfig/hello-worldnombres en mayúsculas de sus variables Spring Boot. Por ejemplo, una variable llamada server.portseguiría la forma SERVER_PORTcomo una variable de entorno:

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

El mecanismo que se explota aquí es que las aplicaciones Spring Boot tomarán la lista de propiedades y luego las traducirán, haciendo todo en mayúsculas y reemplazando los puntos con guiones bajos. Una vez que la aplicación Spring Boot pasa por este proceso, busca variables de entorno que coincidan y utiliza cualquiera que se encuentre en consecuencia.

Esto se resalta con más detalle en este SO Q&A titulado: ¿Cómo establecer una propiedad Spring Boot con un guión bajo en su nombre a través de Variables de entorno?

Referencias

slm
fuente
1

Se puede hacer usando el servicio Systemd en 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

Puede seguir este enlace para obtener una descripción más elaborada y diferentes formas de hacerlo. http://www.baeldung.com/spring-boot-app-as-a-service

mujeeb rahman
fuente
1

Cree un script con el nombre your-app.service (rest-app.service). Deberíamos colocar este script en el directorio / etc / systemd / system. Aquí está el contenido de muestra del script

[Unit]
Description=Spring Boot REST Application
After=syslog.target

[Service]
User=javadevjournal
ExecStart=/var/rest-app/restdemo.jar
SuccessExitStatus=200

[Install]
WantedBy=multi-user.target

Próximo:

 service rest-app start

Referencias

ingrese la descripción del enlace aquí

ismael
fuente
Se ve igual a esto -> stackoverflow.com/a/30497095/516167
MariuszS