VisualVM通过ssh连接

55

我阅读了如何通过ssh远程使用Visual VM ,但是我认为我没有完全理解,因为无法正常工作。请问有人能给一些示例吗?

ssh -D 9696 login@ip.of.external.machinevisualvm.exe -J-Dnetbeans.system_socks_proxy=localhost:9696 -J-Djava.net.useSystemProxies=true 可以启动 visualvm,但是外部机器的进程不会被显示(只显示本地进程如visualvm自身)。此外,有时候(但不总是),我在ssh窗口中看到 "channel 3: open failed: connect failed: Connection refused" 的消息。

有什么帮助吗?


你不需要从VisualVM连接到远程主机吗?我现在没有机器来测试,但是你只创建了一个socks代理,你仍然需要对其进行一些操作。 - Hans Doggen
谢谢您的评论 - 我尝试了几种“变化”,但都没有起作用。 - bgraves
从2015年开始,您可以隧道连接jmx和rmi端口,请参见我的回答 - Boris Treukhov
9个回答

47
你需要在远程端运行jstatd,或者使用主机:端口指定一个JMX连接。

jstatd:

jstatd -J-Djava.security.policy=permissions.txt [-p port]

之后:添加一个到目标机器的远程连接,并在该远程连接的属性中配置jstatd连接。

(permissions.txt 包含例如以下内容:

grant {
  permission java.security.AllPermission;
};

编辑:(回答评论)

  1. ssh -D 9696 me@remote 并在远程命令行上运行 jstatd,如上所述。 如果你想要将 jstatd 放在不同于默认端口 1099 的端口上,请使用 -p 参数来运行 jstatd。

  2. 在本地机器上运行 visualvm.exe -J-Dnetbeans.system_socks_proxy=localhost:9696 -J-Djava.net.useSystemProxies=true

  3. 在 visual vm 中:添加新的远程连接,并指定远程主机和 jstatd 的端口(默认为 1099,或者如果你在运行 jstatd 时使用了 -p,则是你指定的端口)

    现在你应该可以在 visualvm 中看到远程端的进程了


抱歉,我不太明白。我能在远程端启动jstatd行,但是我需要使用“ssh -D 9696 me@remote”前往那里吗?还是“ssh me@remote”就足够了?我仍然需要代理设置才能使用visualvm等工具。这很尴尬,但我认为我需要一份逐步指南。 - bgraves
  1. 在远程命令行上运行ssh -D 9696 me@remote,然后像上面一样运行jstatd。如果您想将jstatd放在与默认端口1099不同的端口上,请使用-p参数来运行jstatd。
  2. 在本地计算机上运行visualvm.exe -J-Dnetbeans.system_socks_proxy=localhost:9696 -J-Djava.net.useSystemProxies=true
  3. 在visual vm中添加新的远程连接,并将远程主机和jstatd的端口(默认为1099,或者在运行jstatd时指定的端口)指定为远程。
现在您应该可以在visualvm中看到远程端的进程了。
- ankon
2
我尝试了这个,但没有成功。你到底要把远程主机放在哪里?通常你会想要使用“localhost”(关于代理服务器),但是VisualVM抱怨说Local已经被监视了。我尝试了目标主机的内部和外部IP地址,但是我没有看到任何进程。 - Yang
1
@Yang为我工作时使用了目标主机的内部IP。 - itsadok

31
我有另一种解决方案,使用标准的SSH隧道和无需打开防火墙端口。 对我来说,SOCKS代理不起作用。
使用以下选项启动您的JVM: -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=[port1] -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.rmi.port=[port2] 重要的部分是"rmi.server.hostname=localhost"。此外,您需要明确定义两个端口(连接端口和“随机”RMI端口),"jmxremote.rmi.port"至少需要Java 7更新4(我在某处看到过,没有验证这个信息-在服务器上使用"lsof -i"或"netstat -at --numeric-ports"来检查实际使用的端口)。 port1port2可以相同,这样可以减少SSH隧道配置。
(当然,根据您的安全要求,您可以使用身份验证或SSL。)
通过ssh连接到服务器,并将本地的port1port2转发到localhost:port1|2上的服务器。重要提示:port2必须转发到本地机器上相同的端口号。(原因:在通过port1连接后,JVM会告诉JMX客户端端口号port2,客户端会连接到同一主机上的这个端口,即localhost。)
在VisualVM中打开一个JMX连接到localhost:port1(不需要任何代理设置)。

1
很棒的信息...使用SSH隧道解决了我的问题。关键是必须配置和转发2个端口。 - Shane
6
FYI,“port1”可以等于“port2”,因此您可以只使用一个端口。 - Boris Treukhov
1
“ssh -L <local_port_1>:<ip_target_jvm_is_running>:<remote_port_1> -L <local_port_2>:<ip_target_jvm_is_running>:<remote_port_2> localhost” 是连接到服务器并将本地端口1和端口2转发到localhost:port1|2的相应部分吗? - Coder

17

我在通过ssh连接远程应用程序时遇到了同样的问题。

这篇教程帮助我解决了这个问题。http://issamben.com/how-to-monitor-remote-jvm-over-ssh/

要解决这个问题,请确保:

  • 您在jvm配置中设置了两个端口

     -Dcom.sun.management.jmxremote.ssl=false 
     -Dcom.sun.management.jmxremote.authenticate=false 
     -Dcom.sun.management.jmxremote.port=9010
     -Dcom.sun.management.jmxremote.rmi.port=9011
     -Djava.rmi.server.hostname=localhost
     -Dcom.sun.management.jmxremote.local.only=false
    
  • SSH隧道已经成功建立

     ssh -i yourPermissionFile.pem -l username 101.101.101.101 -L 9010:localhost:9010 -L 9011:localhost:9011
    

13

我遇到了jstatd绑定本地主机的问题,所以我不得不键入

jstatd -J-Djava.security.policy=allPerm.policy -J-Djava.rmi.server.logCalls=true -p <port> -J-Djava.rmi.server.hostname=<my ip>

对于 jvisualvm,我使用了这些参数而不是原来的参数

jvisualvm -J-DsocksProxyHost=localhost -J-DsocksProxyPort=<socks-port>

通过ssh代理连接,我可以使用远程机器的真实IP地址。从这个答案中借鉴,我在我的网站上制作了一个完整的提醒..希望你不介意,ankon。顺便说一句,谢谢你 :)


在UI中设置代理对我不起作用,但在命令行上指定它可以。谢谢。顺便说一下,我正在使用版本1.8.0_25(Build 140407)。 - Bin Wang
2
在VisualVM GUI中定义SOCKS代理对我没有起作用。不过这些CLI参数运行良好。 - Will

5
我发现 JVM 参数也很重要:
-J-Dnetbeans.system_socks_proxy=localhost:9696 -J-Djava.net.useSystemProxies=true

我使用的版本是1.3.2,但是它并没有在我的版本上起作用。

因此,我使用“工具”>“选项”>“网络”,在SOCKS设置下手动设置了它。

但是VisualVM仍然无法找到远程进程。因此,我删除了“无代理主机”监听本地主机,因为这可能会阻止它。


我还需要打开本地属性并添加一个jstat配置端口1099(或您为jstatd选择的任何端口)。 - Guss

4

我发现在JVM参数中设置代理无效。至少在版本1.3.3(构建111013)中是如此。在“工具”>“选项”>“网络”中设置代理对我有用。此外,系统范围内的代理设置应该可以工作,但根据定义它会影响所有其他网络连接。


1

我知道这个问题很老了,但是我建议使用更简单的解决方案,而不是使用jstat。

只需要使用SSH和Jvisualvm

  1. 使用sockproxy进行ssh连接(例如:ssh -D 6666 host@123.123.123.123)
  2. 使用sock运行jvisualvm(jvisualvm.exe -J-DsocksProxyHost=localhost -J-DsocksProxyPort=6666)
  3. 添加JXM主机(例如:234.234.234.234:16000)

使用jvisualvm轻松检测内存泄漏,并监视应用程序的CPU和RAM。


0

适用于我的 Google Cloud gcloud:

  • 使用 putty/ssh 创建 SOCKS 隧道(putty 连接 > ssh > 隧道 > 动态源端口 61099 用于 ssh -D61099)
  • Java 选项(!删除您采取的所有其他建议):
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=1099
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
VisualVM: 工具 > 选项 > 网络 > 手动 > SOCKS代理: localhost端口: 61099 按OK,在应用程序树中,右键单击并添加远程主机 使用 VM 的内部 IP(10.128.x.x) 右键单击该主机节点并添加JMX 输入10.128.x.x:1099

0
尝试使用不同版本的jvisualvm(例如,来自https://visualvm.github.io/download.html的最新版本)。
我无法让jvisualvm工作,因为它没有使用SOCKS代理(在ssh -v -D 9696中我没有看到与jvisualvm相关的任何内容)。远程应用程序从未出现在jvisualvm中。但是,VisualVM在几秒钟后显示了它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接