Spring Boot application as a Service

2019-01-04 15:20发布

How to configure nicely Spring Boot application packaged as executable jar as a Service in linux system? Is this recommended approach, or should I convert this app to war and install into Tomcat?

Currently I can run Spring boot application from screen session, what is nice, but requires manual start after server reboot.

What I'm looking for is general advice/direction or sample init.d script, if my approach with executable jar is proper.

16条回答
再贱就再见
2楼-- · 2019-01-04 16:05

If you want to use Spring Boot 1.2.5 with Spring Boot Maven Plugin 1.3.0.M2, here's out solution:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>1.3.0.M2</version>
            <configuration>
                <executable>true</executable>
            </configuration>
        </plugin>
    </plugins>
</build>

<pluginRepositories>
    <pluginRepository>
        <id>spring-libs-milestones</id>
        <url>http://repo.spring.io/libs-milestone</url>
    </pluginRepository> 
</pluginRepositories>

Then compile as ususal: mvn clean package, make a symlink ln -s /.../myapp.jar /etc/init.d/myapp, make it executable chmod +x /etc/init.d/myapp and start it service myapp start (with Ubuntu Server)

查看更多
相关推荐>>
3楼-- · 2019-01-04 16:06

I don't know of a "standard" shrink-wrapped way to do that with a Java app, but it's definitely a good idea (you want to benefit from the keep-alive and monitoring capabilities of the operating system if they are there). It's on the roadmap to provide something from the Spring Boot tool support (maven and gradle), but for now you are probably going to have to roll your own. The best solution I know of right now is Foreman, which has a declarative approach and one line commands for packaging init scripts for various standard OS formats (monit, sys V, upstart etc.). There is also evidence of people having set stuff up with gradle (e.g. here).

查看更多
太酷不给撩
4楼-- · 2019-01-04 16:11

Here is a script that deploys an executable jar as a systemd service.

It creates a user for the service and the .service file, and place the jar file under /var, and makes some basic lock down of privileges.

#!/bin/bash

# Argument: The jar file to deploy
APPSRCPATH=$1

# Argument: application name, no spaces please, used as folder name under /var
APPNAME=$2

# Argument: the user to use when running the application, may exist, created if not exists
APPUSER=$3

# Help text
USAGE="
Usage: sudo $0 <jar-file> <app-name> <runtime-user>
If an app with the name <app-name> already exist, it is stopped and deleted.
If the <runtime-user> does not already exist, it is created.
"

# Check that we are root
if [ ! "root" = "$(whoami)" ]; then
    echo "Must be root. Please use e.g. sudo"
    echo "$USAGE"
    exit
fi

# Check arguments
if [ "$#" -ne 3 -o ${#APPSRCPATH} = 0 -o ${#APPNAME} = 0 -o ${#APPUSER} = 0 ]; then
    echo "Incorrect number of parameters."
    echo "$USAGE"
    exit
fi

if [ ! -f $APPSRCPATH ]; then
    echo "Can't find jar file $APPSRCPATH"
    echo "$USAGE"
    exit
fi

# Infered values
APPFILENAME=$(basename $APPSRCPATH)
APPFOLDER=/var/javaapps/$APPNAME
APPDESTPATH=$APPFOLDER/$APPFILENAME

# Stop the service if it already exist and is running
systemctl stop $APPNAME >/dev/null 2>&1

# Create the app folder, deleting any previous content
rm -fr $APPFOLDER
mkdir -p $APPFOLDER

# Create the user if it does not exist
if id "$APPUSER" >/dev/null 2>&1; then
    echo "Using existing user $APPUSER"
else
    adduser --disabled-password --gecos "" $APPUSER
    echo "Created user $APPUSER"
fi

# Place app in app folder, setting owner and rights
cp $APPSRCPATH $APPDESTPATH
chown $APPUSER $APPDESTPATH
chmod 500 $APPDESTPATH
echo "Added or updated the $APPDESTPATH file"

# Create the .service file used by systemd
echo "
[Unit]
Description=$APPNAME
After=syslog.target
[Service]
User=$APPUSER
ExecStart=/usr/bin/java -jar $APPDESTPATH
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
" > /etc/systemd/system/$APPNAME.service
echo "Created the /etc/systemd/system/$APPNAME.service file"

# Reload the daemon
systemctl daemon-reload

# Start the deployed app
systemctl start $APPNAME
systemctl status $APPNAME

Example: enter image description here

查看更多
爷、活的狠高调
5楼-- · 2019-01-04 16:12

What follows is the easiest way to install a Java application as system service in Linux.

Let's assume you are using systemd (which any modern distro nowadays does):

Firstly, create a service file in /etc/systemd/system named e.g. javaservice.service with this content:

[Unit]
Description=Java Service

[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/data 
ExecStart=/usr/bin/java -Xmx256m -jar application.jar
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Secondly, notify systemd of the new service file:

systemctl daemon-reload

and enable it, so it runs on boot:

systemctl enable javaservice.service

Eventually, you can use the following commands to start/stop your new service:

systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice

Provided you are using systemd, this is the most non-intrusive and clean way to set up a Java application as system-service.

What I like especially about this solution is the fact that you don't need to install and configure any other software. The shipped systemd does all the work for you, and your service behaves like any other system service. I use it in production for a while now, on different distros, and it just works as you would expect.

Another plus is that, by using /usr/bin/java, you can easily add jvm paramters such as -Xmx256m.

Also read the systemd part in the official Spring Boot documentation: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html

查看更多
甜甜的少女心
6楼-- · 2019-01-04 16:12

You could also use supervisord which is a very handy daemon, which can be used to easily control services. These services are defined by simple configuration files defining what to execute with which user in which directory and so forth, there are a zillion options. supervisord has a very simple syntax, so it makes a very good alternative to writing SysV init scripts.

Here a simple supervisord configuration file for the program you are trying to run/control. (put this into /etc/supervisor/conf.d/yourapp.conf)

/etc/supervisor/conf.d/yourapp.conf

[program:yourapp]
command=/usr/bin/java -jar /path/to/application.jar
user=usertorun
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/var/log/yourapp-stdout.log
stderr_logfile=/var/log/yourapp-stderr.log

To control the application you would need to execute supervisorctl, which will present you with a prompt where you could start, stop, status yourapp.

CLI

# sudo supervisorctl
yourapp             RUNNING   pid 123123, uptime 1 day, 15:00:00
supervisor> stop yourapp
supervisor> start yourapp

If the supervisord daemon is already running and you've added the configuration for your serivce without restarting the daemon you can simply do a reread and update command in the supervisorctl shell.

This really gives you all the flexibilites you would have using SysV Init scripts, but easy to use and control. Take a look at the documentation.

查看更多
闹够了就滚
7楼-- · 2019-01-04 16:13

In this question, the answer from @PbxMan should get you started:

Run a Java Application as a Service on Linux

Edit:

There is another, less nice way to start a process on reboot, using cron:

@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar

This works, but gives you no nice start/stop interface for your application. You can still simply kill it anyway...

查看更多
登录 后发表回答