jar 패키지 외부의 구성 파일에 대한 FileInputStreamException으로 인해 Java 데몬이 계속 실패합니다.

jar 패키지 외부의 구성 파일에 대한 FileInputStreamException으로 인해 Java 데몬이 계속 실패합니다.

표준 Debian Stretch(커널 버전 4.9)를 사용하여 Raspberry Pi에서 실행되는 데몬/서비스로 Java 애플리케이션을 구현하고 싶습니다.

Java 애플리케이션이 시작되었지만 jar 외부에 있는 중요한 구성 파일을 읽을 수 없기 때문에 예외가 발생합니다. 이것은 의도적으로 설계된 것입니다. 구성 파일을 jar 외부에 보관하고 싶습니다.

구성 파일을 jar에 넣고 InputStream을 통해 파일을 읽어서 실행했습니다. 그러나 요구 사항은 구성 파일이 jar 내부에 없어야 한다는 것입니다. 터미널을 통해 항아리를 수동으로 시작하는 것도 가능합니다. 루트로 수동 시작 작업에 표시된 대로 파일 권한이 양호해야 합니다.

내 직감은 서비스 시작 중에 작업 디렉터리가 엉망이 된다는 것입니다. 또 다른 직감은 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/

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

다음은 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

시스템 장치에 작업 디렉터리를 설정하지 않았습니다. 당신처럼 보입니다예정된하지만 하나를 설정하려면.

알겠어요:

CHDIR=/opt/servicedir/

그러나 그러한 구성 옵션이 없습니다.

서비스가 시작되는 작업 디렉터리를 설정하려면 다음을 사용하세요.WorkingDirectory=. 예를 들어:

WorkingDirectory=/opt/servicedir

관련 정보