Quero implementar um aplicativo Java como um daemon/serviço que roda no meu Raspberry Pi com Debian Stretch padrão (Kernel versão 4.9).
O aplicativo Java é iniciado, mas lança uma exceção porque não consegue ler um arquivo de configuração importante que reside fora do jar. Isso ocorre intencionalmente. Quero manter os arquivos de configuração fora do jar.
Coloquei-o em execução colocando os arquivos de configuração no jar e lendo os arquivos via InputStream. Mas os requisitos são que os arquivos de configuração não estejam dentro do jar. Iniciar manualmente o jar via terminal também funciona. As permissões de arquivo devem estar corretas, conforme indicado pelo manual de trabalho de inicialização como root.
Meu palpite é que o diretório de trabalho fica confuso durante a inicialização do serviço. Outro palpite é que navegar no sistema de arquivos via FileInputStream causa problemas.
Este é o meu arquivo de serviço:
[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
Permissões de arquivo para tudo em /opt/servicedir/: sudo chmod -R 770 /opt/servicedir/
Exceção do 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'.
Aqui está a linha de código do 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)) {
Responder1
Você não definiu um diretório de trabalho em sua unidade systemd. Parece que vocêpretendidopara definir um, no entanto.
Eu vejo:
CHDIR=/opt/servicedir/
Mas não existe essa opção de configuração.
Para definir o diretório de trabalho com o qual o serviço inicia, useWorkingDirectory=
. Por exemplo:
WorkingDirectory=/opt/servicedir