Spring Boot 2系列(六十一):作为Linux服务运行Java程序

除了使用 java -jar 运行 Spring Boot 应用程序之外,还可以为 Unix 系统制作完全可执行的应用程序。

完全可执行的 jar 可以像任何其他可执行二进制文件一样执行,也可以使用 init.dsystemd 注册。

这有助于在常见的生产环境中安装和管理 Spring Boot 应用程序。

以下操作在 Ubuntu 16.04.4版本上操作

创建可执行应用

Maven 管理的项目,在pom.xml文件中的spring-boot-maven-plugin插件下添加开启可执行文件的配置。

  1. 打包成可执行文件

    1
    2
    3
    4
    5
    6
    7
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
    <executable>true</executable>
    </configuration>
    </plugin>
  2. 通过rzsftpjar包上传到 Linux 服务器。

  3. 修改包的jar包的权限

    1
    2
    # 这个`jar`就变成了 Linux 环境下的一个可执行文件了。
    chmod 777 myapp.jar
  4. 以可执行文件的方式运行 jar

    1
    ./myapp.jar

init.d 方式

  1. 创建软链接

    1
    ln -s /usr/local/java-app/myapp.jar /etc/init.d/myapp

    官文档指示操作:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#deployment-install

  2. 给服务授权为可执行

    1
    /etc/init.d# chmod +x myapp
  3. 查看服务可用命令

    1
    2
    /etc/init.d# ./myapp
    Usage: ./myapp {start|stop|force-stop|restart|force-reload|status|run}
  4. 可执行命令

    1
    2
    3
    4
    5
    6
    7
    /etc/init.d# ./myapp start
    /etc/init.d# ./myapp stop
    /etc/init.d# ./myapp force-stop
    /etc/init.d# ./myapp restart
    /etc/init.d# ./myapp force-reload
    /etc/init.d# ./myapp status
    /etc/init.d# ./myapp run

    以上操作还不算是将 jar 注册为服务来启动.
    服务启动命令应该是:service service_name [start|stop|reload|status],

    或者是:systemctl [tart|stop|reload|status] service_name.service

  5. 以service方式运行

    1
    2
    service myapp start
    提示:Failed to start myapp.service: Unit myapp.service not found.
  6. 将服务注册为系统默认服务

    1
    2
    3
    4
    update-rc.d myapp defaults 
    再次启动服务
    service myapp start
    提示:Job for myapp.service failed because the control process exited with error code. See "systemctl status myapp.service" and "journalctl -xe" for details.
  7. 根据提示查找问题

    1
    2
    3
    systemctl status myapp.service
    提示:Loaded: loaded (/etc/init.d/myqpp; bad; vendor preset: enabled)
    Active: failed (Result: exit-code) since Wed 2018-06-13 18:21:42 CST; 51s ago
  8. 继续查找

    1
    2
    journalctl -xe
    提示:Unable to find Java

    提示是找不到 java,提示内容是服务文件输出的,服务文件中使用的是$JAVA_HOME来查找 java。实际已经配置了 Java 环境,在**/etc/profile** 文件配置了 export JAVA_HOME=/usr/local/java/jdk1.8.0_172 ,问题出在服务文件中的$JAVA_HOME定位不到jdk目录,把文件中的**$JAVA_HOME**用绝对路径显式指定,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # Find Java
    if [[ -n "/usr/local/java/jdk1.8.0_172" ]] && [[ -x "/usr/local/java/jdk1.8.0_172/bin/java" ]]; then
    javaexe="/usr/local/java/jdk1.8.0_172/bin/java"
    elif type -p java > /dev/null 2>&1; then
    javaexe=$(type -p java)
    elif [[ -x "/usr/bin/java" ]]; then
    javaexe="/usr/bin/java"
    else
    echo "Unable to find Java"
    exit 1
  9. 以服务方式启动

    1
    2
    3
    service myapp start                     	 //启动成功
    service myapp status //状态:活动
    systemctl status myapp.service //状态:活动

    目前来看以服务方式启动是成功了,现在访问下服务

  10. 访问服务: http://ip:port/mapping_path //无响应,访问失败。
    使用 ps -ef|grep java 没有看到Java进程,不知具体原因,问题仍未解决。

  11. CentOS 7环境验证
    在 CentOS 7 环境下,截止到第 5 步的操作可正常部署运行可访问,这也是 Spring Boot 官方文档支持的方式。在 Ubuntu 16.04.4版本上就比较诡异了,其它版本是否有差异会造成异常还不确定。
    官方文档:https://docs.spring.io/spring-boot/docs/2.0.2.RELEASE/reference/htmlsingle/

systemd方式

  1. Spring Boot 项目 jar 包是安装在** /var/myapp** 目录下(安装目录根据自己需要而选择)

  2. /etc/systemd/system 目录下创建myapp.service脚本文件

    1
    2
    3
    1. 

    > /etc/systemd/system# touch myqpp.service
  3. 编辑脚本文件内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    [Unit]
    Description=myapp
    After=syslog.target

    [Service]
    #如果没有添加指定用户权限,注释User限制
    #User=myapp
    #jar文件绝对路径
    ExecStart=/var/myapp/myapp.jar
    SuccessExitStatus=143

    [Install]
    WantedBy=multi-user.target

    ExecStart=/var/myapp/myapp.jar此设置可能会提示:Unable to find Java; 也是找不到 java 执行命令;
    改为java命令的绝对路径: ExecStart=/usr/local/java/jdk1.8.0_172/bin/java -jar /var/myapp/myapp.jar

  4. 启用服务

    1
    systemctl enable myapp.service
  5. 查看服务状态

    1
    2
    #绿色 `active(running)`表示启动成功,活动的状态。
    systemctl status myapp.service
  6. 浏览器访问服务地址
    返回成功表示此方式部署的服务成功。

  7. systemctl常用命令

    1
    2
    3
    4
    systemctl start myapp.service         //启动
    systemctl restart myapp.service //重启
    systemctl status myapp.service //查看状态
    systemctl stop myapp.service //停止

问题:init.dsystemd两种方式部署的应用,启动时如何指定配置文件是个问题(像java命令指定配置文件,如:java -jar xxx.jar - -spring.profiles.active=prod),现还没找到方法。

Spring Boot 2系列(六十一):作为Linux服务运行Java程序

http://blog.gxitsky.com/2022/07/18/SpringBoot-61-run-as-linux-service/

作者

光星

发布于

2022-07-18

更新于

2023-03-06

许可协议

评论