我们有一个在 Mac OS X 上运行的 Java 服务器应用程序。
有时,此应用程序会变得无响应,我们不得不使用 来终止它kill -9
。但是,该进程不会消失;它仍然会出现ps
,其名称周围带有括号,STAT 列中有一个问号:
$ ps u -p 776
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
camadmin 776 0.0 0.0 0 0 ?? ?E 5:12PM 0:00.00 (java)
而且服务器使用的端口仍然被绑定:
$ netstat -na | grep 9902
tcp4 0 0 *.9902 *.* LISTEN
即使它不可见lsof
:
$ sudo lsof -P -i tcp | grep 9902
$
由于端口仍然绑定,我们无法重新启动服务器应用程序。除了重新启动机器外,还能做些什么来释放端口并真正终止此进程?
答案1
您的进程正在等待某项操作,然后才能退出。
可能是系统调用。尝试访问已卸载的文件或不可用的网络共享就是一个常见示例。
是否有父进程或子进程也需要被终止?
我不是 MacOS 用户,但在 Linux 上ps wwauxf | less
浏览进程层次结构以查找父进程和子进程很有用。 strace -p [pid]
可能会告诉您一些有关尚未返回的当前系统调用的有用信息。
--
编辑:您的进程是由 launchd 启动的吗?似乎有几个人对此有问题(例如如何在 OS X 上终止“退出”进程(状态 = E)),并且如上所述,您可能需要终止父进程,在本例中为 launchd。这可能并不比重新启动更好。
据推测,launchd 会保持与您的应用程序的连接,以便在应用程序死机时重新启动它,但这在这里并不是那么有帮助。
kill -15 效果会更好吗?即在您进入您所描述的状态之前,而不是作为摆脱该状态的方法。
答案2
状态E
似乎意味着进程正在退出。但你的进程基本上是一个永远不会退出的僵尸进程。我在网上找到的所有内容都表明,除了重新启动之外,你几乎无能为力,例如如何在 OS X 上终止“退出”进程(状态 = E)。如果您不想因为其他服务受到影响而重新启动 OSX 服务器,您可以考虑(作为解决方法)以下任一方法:
将此 Java 服务迁移到单独的 OSX 计算机,您可以在需要时随时重新启动,并且影响最小
如果此服务器上有足够的 RAM,您可以创建一个 VM 并从 VM 内部运行此服务。如果进程变得无响应且不会被终止,您可以重新启动 VM,而不会影响主机操作系统。由于它看起来像 Java,您不一定非要将客户 VM 设置为 OSX。也许可以在 Ubuntu 或 CentOS VM 中尝试一下?您可以将其中任何一个下载为设备(OVA/VDI 文件),并在 30 分钟内将其在 VirtualBox 中启动并运行。在 Linux VM 上甚至可能没有僵尸问题。参见http://virtualboximages.com/Free.VirtualBox.VDI.Downloads