spring boot应用程序在Linux下注册成系统服务

通常,将一个Java程序打包成jar之后,可通过java -jar xxx.jar命令运行,但若是以此方式进行部署,则会发现一些不人性化的地方,例如此程序将会一直在前台运行,终端关闭该Java进程也会停止,即便使用nohup或是screen将程序转入后台运行,在需要对Java程序进行关闭、重启、设置开机自启等管理操作时,都需要繁琐的操作,于是,就有了更简便的方式:将该Java服务注册成Linux系统中的服务,使用Linux系统的服务管理机制来管理Java程序。

spring boot项目中的设置

只需在maven的pom文件中,设置spring-boot-maven-plugin的executable为true即可:

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

Linux系统上的设置

Linux系统的启动和管理(包括系统服务)在历史上一直采用init进程,关于init,摘录了一段维基百科上的简介:

init(为英语:initialization的简写)是 Unix 和 类Unix 系统中用来产生其它所有进程的程序。它以守护进程的方式存在,其进程号为1。Linux系统在引导时加载Linux内核后,便由Linux内核加载init程序,由init程序完成余下的引导过程,比如加载运行级别,加载服务,引导Shell/图形化界面等等。

Unix 系列中(如 System III 和 System V)init的作用,和研究中的 Unix 和 BSD 派生版本相比,发生了一些变化。大多数Linux发行版是和 System V 相兼容的,但是一些发行版如Slackware 采用的是BSD风格,其它的如 Gentoo 是自己定制的。后来Ubuntu[1][2] 和其他一些发行版采用 Upstart[3] 来代替[4] 传统的 init 进程。至2015年,大部分Linux发行版都已采用新的systemd替代System VUpstart,但systemd向下兼容System V

使用init进程来启动服务有两个缺点:

一是启动时间长。init进程是串行启动,只有前一个进程启动完,才会启动下一个进程。

二是启动脚本复杂。init进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

于是,就有了维基百科关于init的简介中所说到的,现目前大部分发行版用来代替initsystemd,在使用了systemd的Linux发行版系统中,系统的第一个进程(PID 等于 1)从init变成了systemd,其他进程都是它的子进程,关于systemd的简介:

systemdLinux电脑操作系统之下的一套中央化系统及设置管理程序(init),包括有守护进程程序库以及应用软件,由Lennart Poettering带头开发。其开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell系统开销的效果,最终代替现在常用的System VBSD风格init程序。

当前绝大多数的Linux发行版都已采用systemd代替原来的System V

systemd在LGPL 2.1及其后续版本许可证下开源发布[1][2]

回到本文的目的中来,将spring boot注册成Linux系统的服务,对应Linux系统的两种启动和管理机制,也有两种方式。

init的方式

在使用init启动和管理的Linux上,将springboot注册成系统服务只需将可执行jar使用符号链接链接到系统的/etc/init.d/目录中即可,对应的命令:

ln -s /jar包的路径/jar文件名称.jar /etc/init.d/服务名称

之后,即可通过service 服务名称 {start|stop|force-stop|restart|force-reload|status|run}等命令来对Java程序进行管理操作。

综合上面关于initsystemd的介绍,以及使用此种方式若想设置服务开机自启还需另外编写脚本的繁杂操作,本文更推荐在已引入systemd的Linux中使用下面的方式注册服务(绝大部分新的Linux发行版都已引入systemd,但仍保留着init)。

systemd的方式

systemd管理的服务文件位于/etc/systemd/system/下,以.service结尾,要将spring boot程序使用此种方式注册成系统服务,则需在此文件夹中创建相应的服务文件xxx.service,在文件中写入如下内容:

[Unit]
Description=myapp
After=syslog.target

[Service]
User=myapp
ExecStart=/var/myapp/myapp.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

其中需要修改的是Description的值以及将/var/myapp/myapp.jar替换成自己的jar文件路径,之后即可通过systemctl {start|stop|restart|status|kill|enable|disable} 服务名称命令或是service 服务名称 {start|stop|restart|status}命令来管理spring boot服务。

上述配置文件示例来自springboot官方文档,关于systemd的服务配置文件,还有很多可配置的选项内容,例如失败重启、服务启动需要的前置和后置服务等等等配置项,是另外一门独立的知识点。

配置文件中可供配置的选项可参考systemd官方文档

配置文件

在jar所在文件夹中创建与jar名称相同但文件后缀为.conf的文件,例如jar名称为myapp.jar,则在同一目录下创建myapp.conf文件,springboot服务启动时会读取该配置文件,配置文件中主要配置的配置项:

选项名称描述
RUN_AS_USER程序运行时使用的Linux用户,未设置时默认为此jar文件所属用户。
LOG_FOLDER主日志文件存放路径,默认为/var/log
RUN_ARGS传递给springboot的启动参数。
JAVA_OPTS传递给jvm的参数(最重要的就是这个,jvm调优时的参数通过此项设置)

完整可配置的选项参考springboot官方文档