问题描述
我正在使用 OpenJDK 64 位服务器 VM(构建 25.275-b01,混合模式)在 Ubuntu 20.04 操作系统上运行 Tomcat 9。 当我尝试使用 jstat、jstack 等收集诊断信息时,我看到未找到 PID。 jps也无法识别Tomcat进程id。
我查看了几个帖子,例如 one、two、three、four 等,但是这些帖子中给出的答案都没有帮助我解决问题!
即使我传递了运行 Tomcat 进程的用户名,jstat 也找不到该进程:sudo -u tomcat jstat -gc 476174 5000
以防万一:
- 我可以看到Tomcat进程是用
-Djava.io.tmpdir=/tmp
启动的 此文件夹归 root 用户所有,但已启用完全权限 (777)。 - 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...