Running a Java process from Systemd

16

5

I'm trying to execute a shell script from systemd. The script runs fine from command line.

The script (runServer.sh), runs up a Java process and looks like this:

#!/bin/bash
java -jar -Dresources=/home/pruss/dev/ServerDeploy5-4.1/Server/resources/MyServer.jar "0" "Test"

Inside /usr/lib/systemd/system (or /lib/systemd/system/ on other OSes) I've created a service file (myService.service):

[Unit]
Description=My Servers service
[Service]
ExecStart=/home/pruss/dev/ServerDeploy5-4.1/Server/runServer.sh
User=root
Type=oneshot
[Install]
WantedBy=multi-user.target

The result

Job for myService.service failed. See "systemctl status myService.service" and "journalctl -xn" for details.

I try:

systemctl status myService.service


   Loaded: loaded (/usr/lib/systemd/system/myService.service; disabled)
   Active: failed (Result: exit-code) since Thu 2015-07-23 12:27:38 BST; 26s ago
   Main PID: 28413 (code=exited, status=203/EXEC)

wax_lyrical

Posted 2015-07-23T11:31:02.640

Reputation: 386

And, if you're getting class not found exceptions - might take a look at my answer on SO https://stackoverflow.com/questions/21503883/spring-boot-application-as-a-service/49482664#49482664 took a few hours of my life to figure out the stupid issue ;-(

– JGlass – 2018-03-26T01:16:15.120

Answers

11

You may not need the shell script. You can start the process from the myService.service file provided you use the full path to both the java binary and the jar file. It should look something like

ExecStart=/usr/bin/java -jar /home/pruss/dev/ServerDeploy5-4.1/Server/resources/MyServer.jar

Works on CentOS 7.2.

siliconrockstar

Posted 2015-07-23T11:31:02.640

Reputation: 211

1my opinion is, that script is easier to maintain... – Betlista – 2018-07-24T12:16:38.147

10

Not sure who gave this a thumbs down..

I found the solution and post it to save others the effort.

What you see above works. However, the final service is thus:

[Unit]
Description=MyProgramThing
[Service]
ExecStart=/home/prus/dev/Blah-4.1/Server/runServer.sh
Type=simple
User=prus
[Install]
WantedBy=multi-user.target

Importantly, inside my shell script, I needed to put in the full path the the .jar file. java -jar /home/myprog.jar etc

i.e. ./myJar.jar did not work. Hope that helps.

wax_lyrical

Posted 2015-07-23T11:31:02.640

Reputation: 386

1How do you account for ExecStop ? – Balaji Boggaram Ramanarayan – 2018-04-20T18:17:01.993

CTRL+C/SIGINT is sent to the java process when you stop the systemd service, if you app responds to that then is good, after the TimeoutStopSec (default : DefaultTimeoutStopSec 90s) it will send sigkill – Radu Toader – 2019-03-09T18:49:05.143

4

Take a look at my answer on stackoverflow which details how to create a systemd service for a Java application:

https://stackoverflow.com/a/22121547/272180

yglodt

Posted 2015-07-23T11:31:02.640

Reputation: 211

1Thanks, Yglodt for filling out what I wrote. I did manage to sort this out a year ago, but if your writing helps anyone else, that's all good. – wax_lyrical – 2016-07-14T08:27:14.453

2

This is my systemd template for java a process

[Unit]
Description=Spring MVC Java Service

[Service]
User=spring-mvc
# The configuration file application.properties should be here:
WorkingDirectory=/usr/local/spring-mvc


# Run ExecStartPre with root-permissions
PermissionsStartOnly=true

ExecStartPre=-/bin/mkdir -p /var/log/spring-mvc


ExecStartPre=/bin/chown -R spring-mvc:syslog /var/log/spring-mvc
ExecStartPre=/bin/chmod -R 775 /var/log/spring-mvc


Environment="ENV=stage"

#https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=
ExecStart=/usr/bin/java \
        -Dlog4j.configurationFile=log4j2-spring.xml \
        -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \
        -Dspring.profiles.active=stage \
        -Denvironment-type=stage \
        -XX:+UseConcMarkSweepGC \
        -XX:CMSInitiatingOccupancyFraction=80 \
        -XX:NewSize=756m \
        -XX:MetaspaceSize=256m \
        -Dsun.net.inetaddr.ttl=5 \
        -Xloggc:/var/log/spring-mvc/gc.log \
        -verbose:gc \
        -verbosegc \
        -XX:+DisableExplicitGC \
        -XX:+PrintGCDetails \
        -XX:+PrintGCDateStamps \
        -XX:+PreserveFramePointer \
        -XX:+StartAttachListener \
        -Xms768m \
        -Xmx768m \
        -XX:+HeapDumpOnOutOfMemoryError \
        -jar spring-mvc.war

SuccessExitStatus=143
StandardOutput=journal
StandardError=journal


KillSignal=SIGINT
TimeoutStopSec=20
Restart=always
RestartSec=5
StartLimitInterval=0
StartLimitBurst=10

LimitNOFILE=500000
LimitNPROC=500000

#https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LimitCPU=
#LimitCPU=, LimitFSIZE=, LimitDATA=, LimitSTACK=, LimitCORE=, LimitRSS=, LimitNOFILE=, LimitAS=, LimitNPROC=, LimitMEMLOCK=, LimitLOCKS=, LimitSIGPENDING=, LimitMSGQUEUE=, LimitNICE=, LimitRTPRIO=, LimitRTTIME=¶

SyslogIdentifier=spring-mvc

[Install]
WantedBy=multi-user.target


# https://www.freedesktop.org/software/systemd/man/journalctl.html
#check logs --- journalctl -u spring-mvc -f -o cat

Radu Toader

Posted 2015-07-23T11:31:02.640

Reputation: 121

0

I had the same problem (code=exited, status=203/EXEC).

Don't forget to give script execution permissions to your user.

You may want to change 777 to something more restrictive.

chmod 777 /home/yourscript.sh

or

chmod u+x /home/yourscript.sh

Then:

systemctl daemon-reload 
systemctl start yourScript.service 
systemctl enable yourScript.service

fabatera

Posted 2015-07-23T11:31:02.640

Reputation: 1

0

You may need to add a WorkingDirectory= so it knows where to run things from.

Christopher Peacock

Posted 2015-07-23T11:31:02.640

Reputation: 1