我们有一些应用程序有时会陷入糟糕的状态,但只能在生产中(当然!).使用堆转储可以帮助收集状态信息,通常更容易使用远程调试器.设置这个很容易 – 只需要添加到他的命令行:
-Xdebug -Xrunjdwp:transport = dt_socket,server = y,suspend = n,address = PORT
似乎没有可用的安全机制,因此在生产中打开调试将有效地允许任意代码执行(通过hotswap).
我们在Solaris 9和Linux(Redhat Enterprise 4)上运行的1.4.2和1.5个Sun JVM的混合.我们如何启用安全调试?任何其他方式来实现我们的生产服务器检测目标?
更新:对于JDK 1.5 JVM,可以指定调试器应绑定的接口和端口.因此,KarlP建议将绑定到环回并仅使用SSH隧道到本地开发人员框中,因为SSH会在服务器上正确设置.
但是,似乎JDK1.4x不允许为调试端口指定接口.因此,我们可以阻止访问网络某处的调试端口,或者在操作系统本身进行某些系统特定的阻塞(IPChains,如Jared建议等)?
更新#2:这是一个黑客,将让我们限制我们的风险,即使在1.4.2 JVMs:
命令行参数:
-Xdebug -Xrunjdwp: transport=dt_socket, server=y, suspend=n, address=9001, onthrow=com.whatever.TurnOnDebuggerException, launch=nothing
Java代码打开调试器:
try { throw new TurnOnDebuggerException(); } catch (TurnOnDebugger td) { //Nothing }
TurnOnDebuggerException可以保证任何其他地方都不会抛出任何异常.
我在Windows机箱上测试了这一点,以证明(1)调试器端口最初没有接收到连接,(2)抛出TurnOnDebugger异常,如上所示导致调试器活着.启动参数是必需的(至少在JDK1.4.2中),但JVM正常地处理垃圾值.
我们正在计划制作一个小型servlet,在适当的安全性之后,可以让我们打开调试器.当然,以后一个人不能关闭它,调试器一旦在它上面仍然会不经意地收听.但是,这些是我们愿意接受的限制,因为生产系统的调试将始终导致以后重新启动.
更新#3:我最后写了三个类:(1)TurnOnDebuggerException,一个简单的’Java Java异常,(2)DebuggerPoller,后台线程检查文件系统上指定文件的存在,以及(3)DebuggerMainWrapper,一个类启动轮询线程,然后反射调用另一个指定类的主方法.
这是它的使用方法:
>在您的启动脚本中用DebuggerMainWrapper替换“main”类
>添加两个系统(-D)参数,一个指定真正的主类,另一个指定文件系统上的文件.
>在命令行上配置调试器,其中添加了onthrow = com.whatever.TurnOnDebuggerException部分
>将上面提到的三个类的jar添加到类路径中.
现在,当您启动JVM时,除了启动后台轮询线程之外,所有内容都是一样的.假设文件(我们称为TurnOnDebugger)最初不存在,则轮询器每N秒检查一次.当poller首先注意到它时,它抛出并立即捕获TurnOnDebuggerException.然后,代理商被启动.
你不能把它关掉,当机器不能很安全的时候.在上面,我不认为调试器允许多个并发连接,因此维护调试连接是您最好的防御.我们选择了文件通知方法,因为它允许我们通过在只有正确使用的权限的目录中指定触发器文件来搭载现有的Unix authen / author.您可以轻松地构建一个通过套接字连接实现相同目的的小型战争文件.当然,由于我们无法关闭调试器,所以我们只能在杀死病毒的应用程序之前收集数据.如果有人想要这个代码,请让我知道.但是,只需要几分钟的时间把它扔在一起.