Quiero implementar una aplicación Java como un demonio/servicio que se ejecute en mi Raspberry Pi con Debian Stretch estándar (versión del kernel 4.9).
La aplicación Java se inicia pero luego genera una excepción porque no puede leer un archivo de configuración importante que reside fuera del jar. Esto es por diseño. Quiero mantener los archivos de configuración fuera del jar.
Lo puse en funcionamiento poniendo los archivos de configuración en el jar y leyéndolos a través de InputStream. Pero los requisitos son que los archivos de configuración no estén dentro del jar. También funciona iniciar manualmente el jar a través de la terminal. Los permisos de archivos deberían estar bien, como lo indica el inicio manual de trabajo como root.
Mi corazonada es que el directorio de trabajo se estropea durante el inicio del servicio. Otra corazonada es que navegar por el sistema de archivos a través de FileInputStream causa problemas.
Este es mi archivo de servicio:
[Unit]
Description=collector
[Service]
User=root
CHDIR=/opt/servicedir/
#application.properties:
ExecStart=/usr/bin/java -jar /opt/servicedir/javaapp.jar
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Permisos de archivo para todo en /opt/servicedir/: sudo chmod -R 770 /opt/servicedir/
Excepción de syslog:
Aug 31 14:38:58 raspberrypi systemd[1]: myservice.service: Main process exited, code=exited, status=1/FAILURE
Aug 31 14:38:58 raspberrypi systemd[1]: myservice.service: Unit entered failed state.
Aug 31 14:38:58 raspberrypi systemd[1]: myservice.service: Failed with result 'exit-code'.
Aug 31 14:39:03 raspberrypi systemd[1]: myservice.service: Service hold-off time over, scheduling restart.
Aug 31 14:39:03 raspberrypi systemd[1]: Stopped service
Aug 31 14:39:03 raspberrypi systemd[1]: Started service
Aug 31 14:39:04 raspberrypi java[7982]: Exception in thread "main" java.lang.ExceptionInInitializerError
Aug 31 14:39:04 raspberrypi java[7982]: #011at foo.bar.Application.<clinit>(Application.java:20)
Aug 31 14:39:04 raspberrypi java[7982]: #011at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Aug 31 14:39:04 raspberrypi java[7982]: #011at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
Aug 31 14:39:04 raspberrypi java[7982]: #011at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Aug 31 14:39:04 raspberrypi java[7982]: #011at java.lang.reflect.Method.invoke(Method.java:497)
Aug 31 14:39:04 raspberrypi java[7982]: #011at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
Aug 31 14:39:04 raspberrypi java[7982]: #011at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
Aug 31 14:39:04 raspberrypi java[7982]: #011at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
Aug 31 14:39:04 raspberrypi java[7982]: #011at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Aug 31 14:39:04 raspberrypi java[7982]: Caused by: java.lang.RuntimeException: Failed to load credentials.properties.
Aug 31 14:39:04 raspberrypi java[7982]: #011at foo.bar.Config.<clinit>(Config.java:60)
Aug 31 14:39:04 raspberrypi java[7982]: #011... 9 more
Aug 31 14:39:04 raspberrypi java[7982]: Caused by: java.io.FileNotFoundException: ./res/credentials.properties (Datei oder Verzeichnis nicht gefunden)
Aug 31 14:39:04 raspberrypi java[7982]: #011at java.io.FileInputStream.open0(Native Method)
Aug 31 14:39:04 raspberrypi java[7982]: #011at java.io.FileInputStream.open(FileInputStream.java:195)
Aug 31 14:39:04 raspberrypi java[7982]: #011at java.io.FileInputStream.<init>(FileInputStream.java:138)
Aug 31 14:39:04 raspberrypi java[7982]: #011at java.io.FileInputStream.<init>(FileInputStream.java:93)
Aug 31 14:39:04 raspberrypi java[7982]: #011at foo.bar.Application.Config.<clinit>(Config.java:44)
Aug 31 14:39:04 raspberrypi java[7982]: #011... 9 more
Aug 31 14:39:04 raspberrypi systemd[1]: myservice.service: Main process exited, code=exited, status=1/FAILURE
Aug 31 14:39:04 raspberrypi systemd[1]: myservice.service: Unit entered failed state.
Aug 31 14:39:04 raspberrypi systemd[1]: myservice.service: Failed with result 'exit-code'.
Aquí la línea de código del código Java:
// this does not work :
String credentialsFilePath = "./res/credentials.properties"
try (FileInputStream in = new FileInputStream(credentialsFilePath)) {
// this line works with the config file inside the jar
String credentialsInJar = "credentials.properties"
try (InputStream in = Config.class.getResourceAsStream(credentialsInJar)) {
Respuesta1
No ha configurado un directorio de trabajo en su unidad systemd. Se parece a tidestinadoSin embargo, establecer uno.
Veo:
CHDIR=/opt/servicedir/
Pero no existe tal opción de configuración.
Para configurar el directorio de trabajo con el que comienza el servicio, utiliceWorkingDirectory=
. Por ejemplo:
WorkingDirectory=/opt/servicedir