Демон Java постоянно дает сбой из-за FileInputStreamException для файлов конфигурации за пределами его пакета jar

Демон Java постоянно дает сбой из-за FileInputStreamException для файлов конфигурации за пределами его пакета jar

Я хочу реализовать Java-приложение как демон/службу, работающую на моем Raspberry Pi со стандартным Debian Stretch (версия ядра 4.9).

Приложение Java запускается, но затем выдает исключение, поскольку не может прочитать важный файл конфигурации, который находится вне jar. Это сделано намеренно. Я хочу хранить файлы конфигурации вне jar.

Я запустил его, поместив файлы конфигурации в jar и прочитав файлы через InputStream. Но требования таковы, что файлы конфигурации не должны находиться внутри jar. Ручной запуск jar через терминал также работает. Разрешения на файлы должны быть в порядке, как указано в рабочем руководстве по запуску с правами root.

Моя догадка в том, что рабочий каталог портится во время запуска службы. Другая догадка в том, что навигация по файловой системе через FileInputStream вызывает проблемы.

Это мой служебный файл:

[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

Разрешения для всех файлов в /opt/servicedir/: sudo chmod -R 770 /opt/servicedir/

Исключение из системного журнала:

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

Вот строка кода из 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)) {

решение1

Вы не установили рабочий каталог в вашем systemd unit. Похоже, вынамеревалсяхотя бы установить его.

Я понимаю:

CHDIR=/opt/servicedir/

Но такой возможности конфигурации нет.

Чтобы задать рабочий каталог, с которого запускается служба, используйтеWorkingDirectory=. Например:

WorkingDirectory=/opt/servicedir

Связанный контент