Der Java-Daemon schlägt aufgrund einer FileInputStreamException für Konfigurationsdateien außerhalb seines JAR-Pakets immer wieder fehl

Der Java-Daemon schlägt aufgrund einer FileInputStreamException für Konfigurationsdateien außerhalb seines JAR-Pakets immer wieder fehl

Ich möchte eine Java-Anwendung als Daemon/Dienst implementieren, die auf meinem Raspberry Pi mit Standard-Debian-Stretch (Kernel-Version 4.9) läuft.

Die Java-Anwendung startet, löst dann aber eine Ausnahme aus, da sie eine wichtige Konfigurationsdatei, die sich außerhalb des Jar befindet, nicht lesen kann. Das ist so beabsichtigt. Ich möchte die Konfigurationsdateien außerhalb des Jar behalten.

Ich habe es zum Laufen gebracht, indem ich die Konfigurationsdateien in das JAR-Archiv gepackt und die Dateien über InputStream gelesen habe. Voraussetzung ist jedoch, dass die Konfigurationsdateien nicht im JAR-Archiv sind. Das JAR-Archiv manuell über das Terminal zu starten, funktioniert auch. Die Dateiberechtigungen sollten in Ordnung sein, wie im Arbeitshandbuch „Start als Root“ angegeben.

Ich vermute, dass das Arbeitsverzeichnis beim Start des Dienstes durcheinander gerät. Eine weitere Vermutung ist, dass die Navigation im Dateisystem über FileInputStream Probleme verursacht.

Dies ist meine Servicedatei:

[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

Dateiberechtigungen für alles in /opt/servicedir/: sudo chmod -R 770 /opt/servicedir/

Ausnahme vom 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'.

Hier die Codezeile aus dem Java-Code:

    //  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)) {

Antwort1

Sie haben in Ihrer systemd-Einheit kein Arbeitsverzeichnis festgelegt. Es sieht so aus, als ob Siebeabsichtigtum jedoch einen festzulegen.

Ich verstehe:

CHDIR=/opt/servicedir/

Eine solche Konfigurationsmöglichkeit gibt es allerdings nicht.

Um das Arbeitsverzeichnis festzulegen, mit dem der Dienst startet, verwenden SieWorkingDirectory=. Zum Beispiel:

WorkingDirectory=/opt/servicedir

verwandte Informationen