我有一个Java进程,它(重新)启动一个Linux进程,这个进程产生两个守护进程并终止。(它是HAProxy的包装器,它被配置为具有2个进程的守护进程)
在每次重新启动时,进程表都会有另外两个僵尸进程。为了防止这些僵尸,我实现了以下内容:
final static SignalHandler _signalHandler = new SignalHandler() {
@Override
public void handle(Signal signal) {
LOG.info("Received signal: {}",signal.getName());
}
};
public HaproxyWrapper() {
Signal.handle(new Signal("CHLD"), _signalHandler);
LOG.info("Registered SIGCHLD signal handler");
}我在输出中看到'Registered‘日志,但没有看到'Received SIGCHLD’。
我做错了吗?
或者,“最简单的工作”--我可以创建一个名为start_haproxy.sh的外壳脚本,它将调用haproxy并处理SIGCHLD。如何在bash中处理SIGCHLD?(处理->忽略)
谢谢。
发布于 2015-01-11 18:17:42
我很确定Java已经忽略了SIGCHLD,这就是你不能捕获它的原因。只有正在运行的进程才会收到这个信号,如果你使用Process.waitFor()命令,你会得到一个子进程已经死亡的通知。
僵尸进程是那些不能被杀死的进程,也就是说,它们应该死了之后还活着,通常是由于操作系统中的问题。我怀疑您关心的是孤立进程,即当您有一个进程的父级已经死亡时。
防止这种情况的最简单方法就是让你的父母等着自己的孩子死去。
BTW守护进程通常作为孤立进程运行。你确定这真的是个问题吗?
发布于 2015-01-12 02:42:06
如果其父进程仍然存在,但尚未对子进程执行wait,则存在僵尸进程。为什么Java不这样做,我不知道。如果父进程退出,子进程将简单地重设为PID 1 (init);在这种情况下,它不能成为僵尸。这就是使用双重forking的原因之一(确保守护进程在启动时立即返回给init,因为它的直接父进程已经退出)。
解决这个问题的简单方法是使用shell脚本,它可以正确地执行守护进程。根据您的Linux发行版的不同,您可能已经有一个执行此操作的实用程序(例如start-stop-daemon。否则,您想要类似于
#/bin/bash
(nohup /path/to/program 0<&- &>/dev/null &)&它完成了必要的双分支。here有一种更长但更彻底的方法。
https://stackoverflow.com/questions/27885884
复制相似问题