service - java_opts - Aplicación Spring Boot como servicio
spring executable jar (15)
¿Estás usando Maven? Entonces deberías probar el complemento AppAssembler:
El complemento Application Assembler es un plugin de Maven para generar scripts para iniciar aplicaciones java. ... Todos los artefactos (dependencias + el artefacto del proyecto) se agregan a la ruta de clase en las secuencias de comandos bin generadas.
Plataformas compatibles:
Variantes de Unix
Windows NT (Windows 9x NO es compatible)
Java Service Wrapper (JSW)
¿Cómo configurar bien la aplicación Spring Boot empaquetada como un archivo ejecutable como un servicio en el sistema Linux? ¿Es este enfoque recomendado, o debo convertir esta aplicación a guerra e instalarla en Tomcat?
Actualmente puedo ejecutar la aplicación de arranque de Spring desde screen
sesión de la screen
, lo que es bueno, pero requiere un inicio manual después del reinicio del servidor.
Lo que estoy buscando es consejo general / dirección o script de muestra init.d
, si mi enfoque con el archivo ejecutable es correcto.
Acabo de hacer esto yo mismo, así que lo que sigue es lo que llevo en términos de un script de controlador de servicio init.d de CentOS. Está funcionando muy bien hasta ahora, pero no soy el hacker de Bash, así que estoy seguro de que hay margen de mejora, por lo que las ideas para mejorarlo son bienvenidas.
Antes que nada, tengo un pequeño script de configuración /data/svcmgmt/conf/my-spring-boot-api.sh
para 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, así que para asegurar 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 utilizo para reiniciar todos mis servicios de Spring Boot. Ese script compartido es donde se puede encontrar la carne 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 de arranque de resorte para realizar un apagado controlado. Sin embargo, en caso de que el Actuador no esté configurado o no se cierre dentro de un marco de tiempo razonable (le doy 5 segundos, lo cual es un poco corto realmente), el proceso será cancelado.
Además, el script supone que el proceso 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.
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 algunos bloqueos básicos 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
En esta pregunta, la respuesta de @PbxMan debería comenzar:
Ejecuta una aplicación Java como un servicio en Linux
Editar:
Hay otra manera menos agradable de iniciar un proceso al reiniciar, usando cron:
@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar
Esto funciona, pero no le ofrece una buena interfaz de inicio / detención para su aplicación. Todavía puedes simplemente kill
todos modos ...
Estoy tratando de hacer aplicaciones Springboot que se presentan como un script de shell de estilo "init.d" con una aplicación comprimida java añadida al final
Al vincular simbólicamente estos scripts desde /etc/init.d/spring-app a /opt/spring-app.jar y modificar el archivo 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 los scripts de estilo init.d de springboot parecen tener las cadenas mágicas necesarias (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 intenté muchas de las recetas 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 encontré que lo siguiente funcionó para mí, cuando el enlace /etc/init.d también estaba en su lugar. Se debe instalar un archivo similar al siguiente 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
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á usando systemd
(que cualquier distribución moderna hoy en día):
En primer lugar, crea un archivo de servicio en /etc/systemd/system
llamado eg javaservice.service
con 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
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
En segundo lugar, notifique systemd
del nuevo archivo de servicio:
systemctl daemon-reload
y lo habilita, por lo que se ejecuta 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é utilizando systemd
, esta es la forma más no intrusiva y limpia de configurar una aplicación Java como servicio del sistema.
Lo que más me gusta de esta solución es el hecho de que no necesita instalar y configurar ningún otro software. El systemd
enviado hace todo el trabajo por usted, y su servicio se comporta como cualquier otro servicio del sistema. Lo uso en producción por un tiempo, en diferentes distros, y funciona como es de esperar.
Otra ventaja es que, al usar /usr/bin/java
, puede agregar fácilmente parámetros jvm
como -Xmx256m
.
Lea también la parte systemd
en la documentación oficial de Spring Boot: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
Los siguientes trabajos para Springboot 1.3 y superior:
Como servicio init.d
El archivo ejecutable tiene los comandos habituales de inicio, detención, reinicio y estado. También configurará un archivo PID en el directorio usual / var / run e iniciará sesión en el directorio habitual / var / log de forma predeterminada.
Solo necesita vincular simbólicamente su jar en /etc/init.d como tal
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 usual
/etc/init.d/myapp start
A continuación, configure un enlace en el nivel de ejecución en el que desee que la aplicación inicie / finalice en el inicio, si así lo desea.
Como un servicio systemd
Para ejecutar una aplicación Spring Boot instalada en var / myapp, puede agregar la siguiente secuencia de comandos en /etc/systemd/system/myapp.service:
[Unit]
Description=myapp
After=syslog.target
[Service]
ExecStart=/var/myapp/myapp.jar
[Install]
WantedBy=multi-user.target
Referencia
Mi script SysVInit para Centos 6 / RHEL (aún no 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 $?
Ejemplo de archivo de configuración /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
No conozco una forma "estándar" de envoltura para hacer eso con una aplicación Java, pero definitivamente es una buena idea (desea beneficiarse de las capacidades de mantenimiento y monitoreo del sistema operativo si están allí) . Se encuentra en la hoja de ruta para proporcionar algo del soporte de la herramienta Spring Boot (maven y gradle), pero por ahora probablemente tenga que hacer la suya propia. La mejor solución que conozco en este momento es Foreman , que tiene un enfoque declarativo y comandos de una línea para el empaquetado de scripts de inicio para varios formatos de sistema operativo estándar (monit, sys V, upstart, etc.). También hay evidencia de personas que han creado cosas con gradle (por ejemplo, here ).
Sé que esta es una pregunta más antigua, pero quería presentar otra forma, que es el appassembler-maven-plugin . Aquí está la parte relevante de mi POM que incluye una gran cantidad de 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>
Se puede hacer usando el servicio Systemd en Ubuntu
<code>
[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
</code>
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
Si desea utilizar Spring Boot 1.2.5 con Spring Boot Maven Plugin 1.3.0.M2, aquí está la 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>
A continuación, compile como ususal: mvn clean package
, mvn clean package
un enlace simbólico ln -s /.../myapp.jar /etc/init.d/myapp
, haga que sea ejecutable chmod +x /etc/init.d/myapp
y lo inicie service myapp start
(con Ubuntu Server)
Siguiendo 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 ejecutando un script de shell que inicie su aplicación java o la inicie desde el sistema mismo, y usted sabe que su ruta de clase es 100% correcta, por ejemplo, ejecutar manualmente la secuencia de comandos de la shell funciona, así como ejecutar lo que tiene en systemd execstart. ¡Asegúrate de ejecutar las cosas como el usuario correcto! En mi caso, probé con diferentes usuarios, después de bastante tiempo de resolución de problemas, finalmente tuve un presentimiento, me puse a rootear como usuario - voila, la aplicación comenzó correctamente. Después de determinar que era un problema de usuario incorrecto, seleccioné chown -R user:user
la carpeta y las subcarpetas y la aplicación se ejecutó correctamente como el usuario y grupo especificado, por lo que ya no es necesario ejecutarla como raíz (mala seguridad).
También puede usar supervisord que es un daemon muy útil, que se puede usar 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 y demás, hay un millón de opciones. supervisord tiene una sintaxis muy simple, por lo que es una muy buena alternativa para escribir scripts de inicio SysV.
Aquí un archivo de configuración de supervisión simple para el programa que está intentando ejecutar / controlar. ( Pon 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ía ejecutar supervisorctl , que le presentará un mensaje donde podría iniciar, detener, 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 demonio supervisord
ya se está ejecutando y ha agregado la configuración para su servicio sin reiniciar el daemon, simplemente puede hacer un comando de reread
a reread
y update
en el shell supervisorctl
.
Esto realmente le da todas las flexibilidades que tendría al usar los scripts de SysV Init, pero es fácil de usar y controlar. Eche un vistazo a la documentation .
COMO SERVICIO DE WINDOWS
Si desea que esto se ejecute en el equipo de Windows, descargue el winsw.exe de
http://repo.jenkins-ci.org/releases/com/sun/winsw/winsw/2.1.2/
Después de eso, renómbrelo al nombre de archivo jar (p. Ej .: your-app .jar)
winsw.exe -> your-app.exe
Ahora crea un archivo xml your-app.xml y copia el siguiente contenido a ese
<?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 estén en la misma carpeta.
Después de este abrir el símbolo del sistema en Administrator previlege 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: gane + r y escriba Herramientas administrativas, luego seleccione el servicio de esa. A continuación, haga clic con el botón derecho y seleccione la opción - ejecutar / detener