如何在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是适当的。
当前回答
我自己刚刚抽出时间来做这件事,所以下面是到目前为止我在CentOS初始化方面的进展。D业务控制器脚本。到目前为止,它工作得很好,但我不是leet Bash黑客,所以我相信还有改进的空间,所以欢迎提出改进的想法。
首先,我为每个服务准备了一个简短的配置脚本/data/svcmgmt/conf/my-spring-boot-api.sh,用于设置环境变量。
#!/bin/bash
export JAVA_HOME=/opt/jdk1.8.0_05/jre
export APP_HOME=/data/apps/my-spring-boot-api
export APP_NAME=my-spring-boot-api
export APP_PORT=40001
我使用CentOS,所以为了确保我的服务在服务器重启后启动,我在/etc/init.d/my-spring-boot-api中有一个服务控制脚本:
#!/bin/bash
# description: my-spring-boot-api start stop restart
# processname: my-spring-boot-api
# chkconfig: 234 20 80
. /data/svcmgmt/conf/my-spring-boot-api.sh
/data/svcmgmt/bin/spring-boot-service.sh $1
exit 0
如您所见,它调用初始配置脚本来设置环境变量,然后调用我用来重新启动所有Spring Boot服务的共享脚本。共享脚本是所有内容的核心所在:
#!/bin/bash
echo "Service [$APP_NAME] - [$1]"
echo " JAVA_HOME=$JAVA_HOME"
echo " APP_HOME=$APP_HOME"
echo " APP_NAME=$APP_NAME"
echo " APP_PORT=$APP_PORT"
function start {
if pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
then
echo "Service [$APP_NAME] is already running. Ignoring startup request."
exit 1
fi
echo "Starting application..."
nohup $JAVA_HOME/bin/java -jar $APP_HOME/$APP_NAME.jar \
--spring.config.location=file:$APP_HOME/config/ \
< /dev/null > $APP_HOME/logs/app.log 2>&1 &
}
function stop {
if ! pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
then
echo "Service [$APP_NAME] is not running. Ignoring shutdown request."
exit 1
fi
# First, we will try to trigger a controlled shutdown using
# spring-boot-actuator
curl -X POST http://localhost:$APP_PORT/shutdown < /dev/null > /dev/null 2>&1
# Wait until the server process has shut down
attempts=0
while pkill -0 -f $APP_NAME.jar > /dev/null 2>&1
do
attempts=$[$attempts + 1]
if [ $attempts -gt 5 ]
then
# We have waited too long. Kill it.
pkill -f $APP_NAME.jar > /dev/null 2>&1
fi
sleep 1s
done
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
esac
exit 0
当停止时,它将尝试使用弹簧引导驱动器来执行受控关机。但是,如果没有配置执行器或未能在合理的时间范围内关闭(我给它5秒,这真的有点短),进程将被杀死。
此外,脚本还假设运行应用程序的java进程是进程详细信息文本中唯一带有“my-spring-boot-api.jar”的进程。在我的环境中,这是一个安全的假设,这意味着我不需要跟踪pid。
其他回答
在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。外部化配置
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).
在这个问题中,@PbxMan的回答可以让你开始:
在Linux上运行Java应用程序作为服务
编辑:
还有另一种不太好的方式在重启时启动进程,使用cron:
@reboot user-to-run-under /usr/bin/java -jar /path/to/application.jar
这是可行的,但不能为应用程序提供良好的启动/停止界面。你仍然可以简单地杀死它……
如果你想使用Spring Boot 1.2.5和Spring Boot Maven Plugin 1.3.0。M2,这是我们的解
<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>
然后像往常一样编译:mvn清洁包,做一个符号链接ln -s /…/myapp.jar /etc/init.chmod +x /etc/init. D /myapp,使其可执行启动myapp服务(Ubuntu服务器)
构建中需要以下配置。Spring Boot项目中的gradle文件。
build.gradle
jar {
baseName = 'your-app'
version = version
}
springBoot {
buildInfo()
executable = true
mainClass = "com.shunya.App"
}
可执行文件= true
这是使jar在unix系统(Centos和Ubuntu)上完全可执行所必需的。
创建一个.conf文件
如果您想配置自定义JVM属性或Spring Boot应用程序运行参数,那么您可以创建一个与Spring Boot应用程序名称相同的.conf文件,并将其与jar文件并行放置。
考虑到your-app.jar是Spring Boot应用程序的名称,那么您可以创建以下文件。
JAVA_OPTS="-Xms64m -Xmx64m"
RUN_ARGS=--spring.profiles.active=prod
LOG_FOLDER=/custom/log/folder
此配置将为Spring Boot应用程序设置64 MB ram并激活prod配置文件。
在linux中创建一个新用户
为了增强安全性,我们必须创建一个特定的用户来运行Spring Boot应用程序作为服务。
创建新用户
sudo useradd -s /sbin/nologin springboot
在Ubuntu / Debian环境下,修改如下命令:
sudo useradd -s /usr/sbin/nologin springboot
设置密码
sudo passwd springboot
使springboot成为可执行文件的所有者
chown springboot:springboot your-app.jar
防止修改jar文件
chmod 500 your-app.jar
这将配置jar的权限,这样它就不能被写入,只能由它的所有者springboot读取或执行。
您可以使用change attribute (chattr)命令将jar文件设置为不可变的。
sudo chattr +i your-app.jar
也应该为相应的.conf文件设置适当的权限,.conf文件只需要读取权限(Octal 400),而不是读取+执行权限(Octal 500)
chmod 400 your-app.conf
创建Systemd服务
/etc/systemd/system/your-app.service
[Unit]
Description=Your app description
After=syslog.target
[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
如果进程被操作系统杀死,将自动重启进程
添加以下两个属性(Restart和RestartSec)以在失败时自动重新启动进程。
/etc/systemd/system/your-app.service
[Service]
User=springboot
ExecStart=/var/myapp/your-app.jar
SuccessExitStatus=143
Restart=always
RestartSec=30
该更改将使Spring Boot应用程序在失败时重新启动,延迟30秒。如果使用systemctl命令停止服务,则不会重新启动。
在系统启动时安排服务
要标记应用程序在系统引导时自动启动,使用以下命令:
在系统启动时启用Spring Boot应用程序
sudo systemctl enable your-app.service
启动或停止服务
systemctl可以在Ubuntu 16.04 LTS和18.04 LTS中用于启动和停止进程。
开始这个过程
sudo systemctl start your-app
停止进程
sudo systemctl stop your-app
参考文献
https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html