如何在Linux系统中将Spring Boot应用程序打包为可执行jar as a Service ?这是推荐的方法吗,还是应该将这个应用程序转换为war并将其安装到Tomcat中?
目前,我可以从屏幕会话运行Spring引导应用程序,这很好,但需要在服务器重新启动后手动启动。
我正在寻找的是一般的建议/方向或样本init。D脚本,如果我的方法与可执行jar是适当的。
如何在Linux系统中将Spring Boot应用程序打包为可执行jar as a Service ?这是推荐的方法吗,还是应该将这个应用程序转换为war并将其安装到Tomcat中?
目前,我可以从屏幕会话运行Spring引导应用程序,这很好,但需要在服务器重新启动后手动启动。
我正在寻找的是一般的建议/方向或样本init。D脚本,如果我的方法与可执行jar是适当的。
当前回答
我知道这是一个老问题,但我想提出另一种方法,即appassembler-maven-plugin。以下是我POM中的相关部分,其中包括许多我们认为有用的额外选项值:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<configuration>
<generateRepository>true</generateRepository>
<repositoryLayout>flat</repositoryLayout>
<useWildcardClassPath>true</useWildcardClassPath>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<configurationDirectory>config</configurationDirectory>
<target>${project.build.directory}</target>
<daemons>
<daemon>
<id>${installer-target}</id>
<mainClass>${mainClass}</mainClass>
<commandLineArguments>
<commandLineArgument>--spring.profiles.active=dev</commandLineArgument>
<commandLineArgument>--logging.config=${rpmInstallLocation}/config/${installer-target}-logback.xml</commandLineArgument>
</commandLineArguments>
<platforms>
<platform>jsw</platform>
</platforms>
<generatorConfigurations>
<generatorConfiguration>
<generator>jsw</generator>
<includes>
<include>linux-x86-64</include>
</includes>
<configuration>
<property>
<name>wrapper.logfile</name>
<value>logs/${installer-target}-wrapper.log</value>
</property>
<property>
<name>wrapper.logfile.maxsize</name>
<value>5m</value>
</property>
<property>
<name>run.as.user.envvar</name>
<value>${serviceUser}</value>
</property>
<property>
<name>wrapper.on_exit.default</name>
<value>RESTART</value>
</property>
</configuration>
</generatorConfiguration>
</generatorConfigurations>
<jvmSettings>
<initialMemorySize>256M</initialMemorySize>
<maxMemorySize>1024M</maxMemorySize>
<extraArguments>
<extraArgument>-server</extraArgument>
</extraArguments>
</jvmSettings>
</daemon>
</daemons>
</configuration>
<executions>
<execution>
<id>generate-jsw-scripts</id>
<phase>package</phase>
<goals>
<goal>generate-daemons</goal>
</goals>
</execution>
</executions>
</plugin>
其他回答
在systemd单元文件中,您可以通过目录或EnvironmentFile设置环境变量。我建议这样做,因为这似乎是最小的摩擦。
示例单元文件
$ cat /etc/systemd/system/hello-world.service
[Unit]
Description=Hello World Service
After=systend-user-sessions.service
[Service]
EnvironmentFile=/etc/sysconfig/hello-world
Type=simple
ExecStart=/usr/bin/java ... hello-world.jar
然后在/etc/sysconfig/hello-world下设置一个文件,其中包含Spring Boot变量的大写名称。例如,一个名为server的变量。port将遵循SERVER_PORT形式作为环境变量:
$ cat /etc/sysconfig/hello-world
SERVER_PORT=8081
这里所利用的机制是Spring Boot应用程序将获取属性列表,然后转换它们,将所有内容都改为大写,并将点替换为下划线。一旦Spring Boot应用程序完成了这个过程,它就会寻找匹配的环境变量,并相应地使用找到的环境变量。
在这篇题为:如何通过环境变量在其名称中设置带有下划线的Spring Boot属性的SO Q&A中强调了更多细节?
参考文献
第四部分。弹簧引导功能- 24。外部化配置
下面是在Linux中将Java应用程序作为系统服务安装的最简单方法。
让我们假设你正在使用systemd(现在任何现代发行版都是这样):
首先,在/etc/systemd/system目录下创建一个服务文件,例如javaservice。服务内容如下:
[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 --server.port=8081
SuccessExitStatus=143
TimeoutStopSec=10
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
其次,通知systemd新的服务文件:
systemctl daemon-reload
并启用它,以便它在引导时运行:
systemctl enable javaservice.service
最后,您可以使用以下命令来启动/停止您的新服务:
systemctl start javaservice
systemctl stop javaservice
systemctl restart javaservice
systemctl status javaservice
如果使用systemd,这是将Java应用程序设置为系统服务的最非侵入性和最干净的方法。
我特别喜欢这个解决方案的地方在于,您不需要安装和配置任何其他软件。所提供的systemd为您完成所有工作,您的服务就像任何其他系统服务一样。我现在在生产环境中使用了一段时间,在各种发行版上,它就像你期望的那样工作。
另一个优点是,通过使用/usr/bin/java,您可以轻松添加jvm参数,如-Xmx256m。
请阅读官方Spring Boot文档中的systemd部分: http://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
您正在使用Maven吗?那么你应该试试AppAssembler插件:
Application Assembler Plugin是一个Maven插件,用于生成启动java应用程序的脚本. ...所有工件(依赖项+项目中的工件)都被添加到生成的bin脚本中的类路径中。 支持平台: unix变体 Windows NT(不支持Windows 9x) Java服务包装器(JSW)
参见:http://mojo.codehaus.org/appassembler/appassembler-maven-plugin/index.html
我的SysVInit脚本Centos 6 / RHEL(还不理想)。这个脚本需要ApplicationPidListener。
/etc/init.d/app的源代码
#!/bin/sh
#
# app Spring Boot Application
#
# chkconfig: 345 20 80
# description: App Service
#
### BEGIN INIT INFO
# Provides: App
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: Application
# Description:
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
exec="/usr/bin/java"
prog="app"
app_home=/home/$prog/
user=$prog
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
lockfile=/var/lock/subsys/$prog
pid=$app_home/$prog.pid
start() {
[ -x $exec ] || exit 5
[ -f $config ] || exit 6
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 1
echo -n $"Starting $prog: "
cd $app_home
daemon --check $prog --pidfile $pid --user $user $exec $app_args &
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc -p $pid $prog
retval=$?
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
stop
start
}
reload() {
restart
}
force_reload() {
restart
}
rh_status() {
status -p $pid $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
restart
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?
配置文件/etc/sysconfig/app示例:
exec=/opt/jdk1.8.0_05/jre/bin/java
user=myuser
app_home=/home/mysuer/
app_args="-jar app.jar"
pid=$app_home/app.pid
对于SpringBoot 2.4.4,除了由 @ismael
我在maven pom.xml中有以下内容,使其成为可执行jar
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>