获取 Spring Boot 应用的 PID

PID 是进程标识符(Process Identifier)的缩写。在操作系统中,每个运行的进程都被分配一个唯一的 PID,用于标识进程。PID 通常是一个整数值,可以用来跟踪和管理进程的状态、资源分配以及进程间的通信。

本文将会介绍几种获取 Spring Boot 应用 PID 的方法。

ApplicationPidFileWriter

ApplicationPidFileWriter 是 Spring Boot 提供的一个 Listener,它可以在应用启动后把 PID 写入到指定的文件。

它需要在启动前,通过编程式配置到应用中,并且需要在配置文件中指定要写入 PID 的文件。

application.yaml 配置如下:

spring:
  pid:
    # 写入 PID 的文件,可以是相对路径或绝对路径
    file: app.pid
    # 如果 PID 无法写入,是否抛出异常
    fail-on-write-error: true

在启动前,配置 ApplicationPidFileWriter 监听器:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.ApplicationPidFileWriter;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        
        SpringApplication springApplication = new SpringApplicationBuilder()
                    .listeners(new ApplicationPidFileWriter()) // PID 监听
                    .sources(DemoApplication.class) // 启动类
                    .build(args) // 启动参数
                    ;
        // 启动
        springApplication.run(args);
    }
}

启动应用,当前的 PID 就会被写入到 spring.pid.file 指定的文件中。

$! 变量

如果你的应用是运行在 Linux 环境中,且你不想修改源码、配置。那么可以在启动应用时通过 Shell 变量 $! 来获取到应用的 PID。

在 Shell 中,$! 是一个特殊的变量,用于获取最近一个在后台运行的进程的 PID。当你在 Shell 中启动一个命令或脚本时,如果将其放在后台运行(使用 &),此时,使用 $! 可以获取到该后台进程的 PID。

例如启动名为 springdoc.jar 的 jar:

nohup java -jar springdoc.jar & echo $! > app.pid

nohup 命令的目的是保证当前 SSH 连接断开后,程序不会退出,Java 启动命令后的 & 表示在后台运行程序。紧接着使用 echo 命令把 $! 变量通过重定向符 > 输出到指定的文件,也就是 app.pid

在 Spring Boot 运行时获取到 PID

上述 2 种方式都是在 Spring Boot 应用启动时把 PID 输出到文件。有时我们可能想获取一个正在运行的 Spring Boot 应用的 PID。

这里介绍 2 种方式。

jps 命令

你可以使用 JDK 提供的 JPS 命令。由于这是 JDK 提供的工具,所以可以在任何操作系统下使用

需要在机器上安装 JDK 以及正确地配置了环境变量。

直接执行 jps 命令,列出所有 Java 进程的 pid 以及对应的进程名称:

$ jps
1562033 Jps
1486028 springdoc.jar

如上,你可以看到 springdoc.jar 的进程 ID 是 1486028

jps 本身也是一个 Java 程序,所以它的进程 ID 也会出现在命令结果列表中。

ps 命令

如果你的机器未安装 JDK,且运行环境是 Linux 系统,那么还可以通过 ps 命令配合表达式来查询指定进程的 PID。

如下:

$ ps -ef | grep start-site-exec.jar
root     1486028       1  0 Sep18 ?        00:04:49 java -jar start-site-exec.jar
root     1562091 1560066  0 10:04 pts/0    00:00:00 grep start-site-exec.jar

解释如下:

  • ps 是一个用于查看当前运行进程的命令。
  • -efps 命令的选项之一,用于显示所有进程的详细信息,包括进程的用户、进程ID(PID)、父进程ID(PPID)、CPU使用情况等。
  • | 是管道符号,用于将一个命令的输出作为另一个命令的输入。
  • grep 是一个用于在文本中搜索指定模式的命令。
  • start-site-exec.jar 是要搜索的进程名称或关键字。

综合起来,ps -ef | grep start-site-exec.jar 的作用是:

  1. ps -ef 显示所有运行中的进程的详细信息。
  2. |ps -ef 命令的输出作为 grep 命令的输入。
  3. grep start-site-exec.jar 在输入的进程信息中搜索包含 “start-site-exec.jar” 关键字的行,并将匹配的行输出。

通过这个命令,可以筛选出正在运行的包含 “start-site-exec.jar” 关键字的进程,并查看与该进程相关的详细信息,如进程ID、用户等。