Search code examples
javaspring-bootcentossystemctl

systemd Unable to find Java


I'm facing a strange behaviour on a Centos Dist trying to run a bootable jar created with spring boot.

If I run the jar app from the shell it runs perfectly

enter image description here

When running the app with a service created with the following config:

[Unit]
Description=app
After=syslog.target

[Service]
ExecStart=/foo/bar/app.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
~

I keep getting the error "Unable to find Java"

enter image description here

I checked the $PATH and $JAVA_HOME properties and they are set up correctly (I don't think this adds more information because the bootable jar runs correctly without beeing a service)

What I'm doing wrong? Been messing around this problem for 3 days and it's driving me mad.


Solution

  • The long and short of the issue is that systemd does not run services in the same context as the user shell, and the mechanism used for running .jar files directly uses the PATH variable to determine the location of the JRE for running the jar.

    If java was on the default systemd path, then the service would start by default. The default path for systemd definitely does not contain the path that you're specifying for java.

    To address the PATH variable not being set sufficiently, we're going to update the service configuration with a PATH environment variable more suitable to it. To accomplish this, we need to add a Environment variable to the [Service] section of the service definition file.

    [Unit]
    Description=app
    After=syslog.target
    
    [Service]
    Environment=PATH=/usr/lib/jvm/jdk-14.0.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    ExecStart=/foo/bar/app.jar
    SuccessExitStatus=143
    
    [Install]
    WantedBy=multi-user.target
    

    Then we reload systemd (systemctl daemon-reload), and we should be able to start the service (systemctl start blah.service).

    It would probably be significantly easier if the jre you want to use is integrated into the OS; it saves having to futz around with the PATH, and would survive upgrades to java, which would alter the path, requiring an update to the service definition - there's a pretty good guide here as to how to install it, system integrated:

    • Download rpm
      • wget --no-check-certificate -c --header "Cookie: oraclelicense=accept-securebackup-cookie" https://download.oracle.com/otn-pub/java/jdk/14.0.2+12/205943a0976c4ed48cb16f1043c5c647/jdk-14.0.2_linux-x64_bin.rpm
    • Install locally
      • yum localinstall jdk-14.0.2_linux-x64_bin.rpm
    • Use alternatives to configure java
      • alternatives --config java
    • Check after setting
      • java -version