jps、jstat、jstack 等命令显示“<pid> not found”

问题描述

我正在使用 OpenJDK 64 位服务器 VM(构建 25.275-b01,混合模式)在 Ubuntu 20.04 操作系统上运行 Tomcat 9。 当我尝试使用 jstat、jstack 等收集诊断信息时,我看到未找到 PID。 jps也无法识别Tomcat进程id。

我查看了几个帖子,例如 onetwothreefour 等,但是这些帖子中给出的答案都没有帮助我解决问题!

即使我传递了运行 Tomcat 进程的用户名jstat 也找不到该进程:sudo -u tomcat jstat -gc 476174 5000

以防万一:

  1. 我可以看到Tomcat进程是用-Djava.io.tmpdir=/tmp启动的 此文件夹归 root 用户所有,但已启用完全权限 (777)。
  2. Tomcat 进程启动时,我可以看到一个名为 systemd-private-e6d8b5dc224848f8a64a3e943ac2e9c4-tomcat9.service-UH5knj文件夹(服务后的最后几个字符 - 每次重新启动进程时更改)以所有者身份创建(可能是因为我启动了 tomcat服务使用 sudo service tomcat9 start) 并且此文件夹的权限为 rwx------

有关如何解决此问题的任何提示

谢谢, 舒巴纳

解决方法

所有这些工具(jstack、jmap、jstat...)都依赖于 communication 和目标 JVM 通过 // MyPlugin.java String myProp = (String) project.getRootProject().getProperties().getOrDefault("myProp",null); Gradle gradle = project.getRootProject().getGradle(); if ((myProp == null) && (gradle instanceof ExtensionAware)) { ExtensionAware gradleExtensions = (ExtensionAware) gradle; myProp = (String) gradleExtensions.getExtensions().getExtraProperties().get("myProp"); } 目录。

显然 Tomcat 运行在不同的挂载命名空间中,因此其 settings.gradle 目录与当前 shell 的 /tmp 目录不同。要验证这一点,请运行

/tmp

并检查 /tmp 数字是否不同。

不幸的是,JDK 8 工具不支持 Linux 命名空间。您可以尝试 nsenter 在 Tomcat 的命名空间下启动这些工具。

或者简单地使用 JDK 11(或更新的)工具,这些工具支持开箱即用的容器(以及命名空间)。它们还适用于在 JDK 8 下运行的应用程序,例如JDK 11 中的 jstack 可以转储 JDK 8 进程的线程。

或者,有一个小的 jattach 实用程序可用于代替 jstack、jmap 和 jcmd。它还支持开箱即用的容器。它不需要安装 - 只有一个 standalone binary

,

在 Ubuntu 20 中,Tomcat 9 服务默认在私有 tmp 空间中运行,因此 Java 工具无法找到其 pid。

此私有 tmp 设置在 /lib/systemd/system/tomcat9.service 中定义为 PrivateTmp。默认设置为“是”。您可以直接编辑该文件,但推荐的更改方法是使用以下命令创建覆盖文件:

sudo systemctl edit tomcat9

在文件中添加以下内容并保存:

[Service]
PrivateTmp=no
ReadWritePaths=/tmp/

它将使用您的内容创建此文件:/etc/systemd/system/tomcat9.service.d/override.conf

然后你需要重新加载systemd守护进程并重启Tomcat:

sudo systemctl daemon-reload
sudo systemctl restart tomcat9

您现在应该可以直接使用 sudo 调用 java 工具,例如sudo jstat...。出于某种原因,当我尝试使用 sudo -u tomcat jstat...

作为 tomcat 用户运行它时它不起作用