linux下jcmd无法获取jvmdump

摘要:
现象:两天前在Linux上的服务中发生了莫名其妙的内存溢出,但发现jcmd无法用于连接到jvm以获取转储。现象:[root@host-12.131.14.15bin]#./jcmd19652GC。heap_dump1965 2:com.sun.tools.attach.AttachNotSupportedException:无法打开套接字文件:targetprocessnotre

现象:

前两天在linux上的服务出现莫名其妙的内存溢出.却发现无法用jcmd连接jvm获取dump.现象:

[root@host-12.131.14.15 bin]# ./jcmd 19652 GC.heap_dump 
19652:
com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
 at sun.tools.attach.LinuxVirtualMachine.<init>(LinuxVirtualMachine.java:106)
 at sun.tools.attach.LinuxAttachProvider.attachVirtualMachine(LinuxAttachProvider.java:63)
 at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:208)
 at sun.tools.jcmd.JCmd.executeCommandForPid(JCmd.java:147)
 at sun.tools.jcmd.JCmd.main(JCmd.java:131)

解决方案:

如果启动用户不是同一个,切换成同一用户.
使用命令如下:
sudo -u [userid] /jcmd 19652 GC.heap_dump 
 
如果启动用户已经是同一个还报错,则去/usr/lib/systemd/system/   服务位置 ,观察服务对应的PrivateTmp属性是否为true.具体如下:
-----------------------
[unit]
description=xxx
[Service]
Type=forking
ExecStartPre=/
ExecStart=
ExecStop=
PrivateTmp=true
[Install]
WantedBy=multi-user.target
-------------------------
 
若PrivateTmp为true,改为false,并使用如下命令刷新服务即可.
--------------------------
systemctl daemon-reload
systemctl restart [servicename]
systemctl status [servicename]
---------------------------

原理解析:

jcmd原理

  • 当使用此命令dump内存时.在连接对应java进程的pid之前,将会jcmd会生成一个.attach_pid在目标程序的工作目录或者/tmp.
  • 然后jcmd发送SIGQUIT到目标进程.当虚拟机获取到这个信号并且发现了.attache_pid,将会开启一个AttachListener 进程.
  • AttachListener 进程使用UNIX 的socket/tmp/.java_pid去和jcmd工具打交道
  • 考虑到安全原因,当一个连接(从jcmd发出的)被接收后,虚拟机会检查socket连接的创建的用户是否和jvm进程的euid或egid一致.这是为jcmd在不同用户的情况不工作的原因.(root的情况也不可使用)
  • jcmd连接上socket后,将会收到dumpheap.

privateTmp

  • 本问题排查时,其实用户已经是同一个用户,但是获取不到,是因为服务的privateTmp机制.当service unit中的privateTmp设置为true时,service会将$tmp_file放在linux的tmp/systemd-private-xxxxx-[servicename].service/xxx中.
  • privateTmp用于设置是否使用私有的tmp目录,那么只要设置使用这个属性的service,都会使用私有的tmp目录。 比如说:   nginx会有一个systemd-private-xxx-nginx.service/tmp目录 
  • 默认的/tmp目录一般所有用户的所有service共享的,对于所有用户及用户运行的程序来说来说,都会有读和写的权限.会存在一些安全性问题.把各个service的tmp目录隔离开的话,可以保证一定的安全性.
  • 对于这个jcmd无法heapdump的问题,在能确认服务器安全的情况下,完全可以考虑关闭掉该配置项.当然,如果服务器安全得不到保障的情况下,或者应用在跑不能重启的情况下,可以通过更改service unit中的execStart execStop对应中的脚本来解决.
例如,我们服务的命令如下:
-----------------------
[unit]
description=xxx
[Service]
Type=forking
ExecStartPre=/
ExecStart=/opt/app/start.sh
ExecStop=/opt/app/stop.sh
PrivateTmp=true
[Install]
WantedBy=multi-user.target
-------------------------
可以通过修改/opt/app/stop.sh脚本,通过stop.sh中的
./jcmd 19652 GC.heap_dump /opt/xxx/servicedump.hprof 来获取dump.

参考说明:

  1. privateTmp介绍 https://www.cnblogs.com/lihuobao/p/5624071.html
  2. https://lists.centos.org/pipermail/centos/2015-April/151589.html
  3. http://0pointer.de/blog/projects/security.html
  4. https://access.redhat.com/blogs/766093/posts/1976243

免责声明:文章转载自《linux下jcmd无法获取jvmdump》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows、Mac 命令行启动程序(为了查看Electron打包后主进程日志)MySQL/MariaDB数据库的性能测试下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

saltstack--史上最细致安装攻略!亲测无坑

准备一台虚拟机node1: [root@linux-node1 pillar]# ifconfig ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.88.137 netmask 255.255.255.0 broadcast 1...

ramdisk文件系统的介绍与制作【转】

转自:https://blog.csdn.net/silent123go/article/details/52642841 一、文件系统与根文件系统    1、文件系统        文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)分区上的文件的存储方法和数据结构,即在存储设备上组织文件的方法。        看了...

如何创建Debian二进制包(译)

如何创建Debian二进制包 1 简介我们采用这样的方法所创建的文档的用途只是安装在我们自己的系统上,而不是将他们提交到Debian的官方版本中。如果我们要进行官方的开发,我们就需要参考Debian New Maintainers' Guide。通常Debian的软件包可以得到一个适当的源码包,在这个源码包中包含有在创建Debian的二进制包时自动处理...

linux下查看进程+杀死进程方法大全

常规篇: 首先,用ps查看进程,方法如下: $ ps -ef ……smx 1822 1 0 11:38 ? 00:00:49 gnome-terminalsmx 1823 1822 0 11:38 ? 00:00:00 gnome-pty-helpersmx 1824 1822 0 11:38 pts/0 00:00:02 bashsmx 1827 1 4...

Linux中获取本机网络信息的几个函数及应用

一、读取/etc/hosts 几个函数 头文件<netdb.h> 1.void sethostent(int stayopen);//开打/etc/hosts 配置文件 2.struct hostent * gethostent(void);//读取配置文件 3.void  enthostent(void);//关闭 /etc/hosts 文件...

Linux内核配置、编译及Makefile简述

Hi,大家好!我是CrazyCatJack。最近在学习Linux内核的配置、编译及Makefile文件。今天总结一下学习成果,分享给大家^_^ 1.解压缩打补丁 首先是解压缩你获取到的Linux内核。这里我用到的是linux.2.22.6版本的内核。在Linux下命令行通过tar xjf linux.2.22.6.tar.bz2解压内核。然后,如果你需要对...