
Estoy intentando aprovisionar aplicaciones Spring-boot (desarrolladas por otra persona; no soy un programador de Java) en Ubuntu 18.04. El desarrollador había agregado previamente enlaces simbólicos /etc/init.d
para habilitar el servicio; comienza bien en el arranque. Sin embargo, si el servicio falla posteriormente, systemd aún informa que se está ejecutando:
[email protected]:/var/log/apps# systemctl status crm-service
● crm-service.service - LSB: crm-service
Loaded: loaded (/etc/init.d/crm-service; generated)
Active: active (exited) since Wed 2020-04-15 12:27:15 BST; 3h 56min ago
Docs: man:systemd-sysv-generator(8)
Process: 8656 ExecStop=/etc/init.d/crm-service stop (code=exited, status=0/SUCCESS)
Process: 8703 ExecStart=/etc/init.d/crm-service start (code=exited, status=0/SUCCESS)
Apr 15 12:27:15 example.com systemd[1]: Starting LSB: crm-service...
Apr 15 12:27:15 example.com crm-service[8703]: /var/services/crm-service.conf: line 1: -Xms96M: command not found
Apr 15 12:27:15 example.com crm-service[8703]: Started [8747]
Apr 15 12:27:15 example.com systemd[1]: Started LSB: crm-service.
mientras veo elmismo archivo de unidad systemdPara Springboot publicado en Internet, no veo nada allí que pueda resolver este problema.
- ¿Cómo consigo que systemd vea el verdadero estado del servicio? (abrirá un conector de escucha, pero en un puerto alto aleatorio)
- ¿Hay alguna manera de hacer que systemd lo pruebe?suavemente¿Reiniciar un servicio que sabe que ha fallado?
Respuesta1
Systemd tiene muchas críticas y muchas de ellas están bastante bien, pero no lo es.Systemd puede rastrear todos los procesos y subprocesos bifurcados (o clonados) desde el script de inicio y considerar el servicio inactivo si ninguno de ellos permanece.
El primer problema que puedo ver: systemd no usa scripts de inicio/detención /etc/init.d
, es solo un complemento de compatibilidad para eso. En cambio, systemd utiliza archivos unitarios, es decir, un archivo de configuración para todos sus servicios.
El módulo systemd sysv init compat genera efectivamente un archivo de unidad para todos los servicios en /etc/init.d
. Esto no siempre está bien, porque los scripts de inicio omiten la información requerida (o es imposible extraerla de ellos).
Este módulo de compatibilidad funciona de manera que systemd considera que el script de inicio falló y, por lo tanto, el servicio no funciona, si su código de salida no es cero. El código de salida cero significa una ejecución exitosa. Si el script de inicio tiene errores y proporciona un código de salida cero incluso en caso de falla, engañará a systemd.
La causa más probable del error de su script de inicio es que inicia el proceso en segundo plano y luego sale siempre con cero. Mi experiencia común con la mayoría de los scripts de inicio escritos por proveedores personalizados es que... tal vez la mayoría de ellos tengan un importante margen de mejora. No te fíes de ellos, mira lo que hacen y arréglalos. En tu caso, lo mejor sería comprobarlo,
- Cómo inicia tu aplicación java
- donde empieza
- ¿Con qué usuario comienza?
Y reproduzca la misma funcionalidad con un archivo unitario.
No hay forma de reiniciar automáticamente los scripts de inicio desde systemd, pero es posible desde archivos unitarios.
Tenga en cuenta que si un programa Java falla aleatoriamente, también es un problema grave. Todos los marcos de Java sensatos manejan correctamente sus propios errores fatales (capturan todas las excepciones, las registran y continúan).
Otro error muy probable en el script de inicio es que no encuentra su JVM (muy probablemente: /usr/bin/java), por lo que lo sustituye por una cadena vacía, lo que provoca que intente iniciar los indicadores de JVM como un comando de shell. . Obviamente no hay ningún -Xms96M
comando en su sistema, pero /usr/bin/java -Xms96M ...
funcionaría.
Un archivo de unidad de ejemplo para una aplicación de arranque de primavera:
[Unit]
Description=Crm Spring Boot App Example
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/java -Xms96M ...other flags... your.spring.boot.jar
User=exampleuser
Group=examplegroup
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=exampleapp
WorkingDirectory=/path/to/app/home
[Install]
WantedBy=multi-user.target
Alias=exampleapp.service
Este archivo de unidad también redirige la salida estándar y el error del proceso Java al syslog.
Para reiniciar automáticamente la aplicación, inserte
RestartSec=5s
Restart=on-failure
en la [Service]
sección.
Hay un tutorial de systemd sobreGoLinuxCloud.com.