当前位置: 首页 > 知识库问答 >
问题:

如何防止ctrl-c杀死Java中派生的进程

长孙泉
2023-03-14

[注意:这与如何从Java程序启动完全独立的进程有关?但不同]

我希望能够从一个“管理器”Java进程中派生出外部进程(shell脚本),当JVM被杀死时,该进程应该继续运行——但当我杀死父Java程序时,子Java程序似乎也被杀死(注意,如果JVM自然退出,行为会有所不同)。我拥有的最简单的测试程序是:

public class Runit {

    public static void main(String args[]) throws IOException, InterruptedException {
        Runtime.getRuntime().exec(args[0]);

        // doesn't work this way either
        // ProcessBuilder pb = new ProcessBuilder(args[0]);
        // pb.start();

        while (true) {
            System.out.println("Kill me");
            Thread.sleep(2000);
        }
    }
}

和外部脚本:

#!/bin/sh

while [ 1 ] ; do 
    ls
    sleep 1
done

作为

java-带有依赖项的类路径jar。罐子温度。执行官。快跑快跑。嘘

如果管理器只是退出(即在Java程序中取出“while”循环),那么生成的进程将继续运行,但当我按下Ctrl键时,外部程序也会被杀死,这不是我想要的。

我在Ubuntu上使用OpenJDK 1.6。

Edit1:将exec更改为

Runtime.getRuntime().exec("/usr/bin/nohup " +  args[0]);

没用。

Edit2:添加一个shutdown hook(如如何在Java中优雅地处理SIGKILL信号所述)并不会阻止Ctrlc被传播到子级。

共有3个答案

司寇羽
2023-03-14

你必须让它成为一个守护进程。不要害怕它不是一部恐怖电影。简单地说,你需要将你的进程从控制终端会话中分离出来。我总是以一种oposite的方式做这件事:启动Java的外壳脚本。

以下是一个解释:

http://en.wikipedia.org/wiki/Daemon_(计算)

您也可以使用“jvm关闭钩子”,但它们在某些情况下不起作用。

公孙嘉禧
2023-03-14

在Linux中,如果您启动另一个进程,它就是您的孩子,您就是他的家长。如果父母被杀,所有的孩子都会被杀,他们的孩子也会被杀(多么可怕的暴行)。

你需要的,是启动一个进程,当你退出你的程序时不会被杀死。所以,你需要生下不是你自己的孩子。这里举例说明了这样做的方法:Linux:防止后台进程在关闭后停止SSH客户端例如使用屏幕实用程序。

权韬
2023-03-14

弗拉基米尔给了我们需要的提示!(对不起,比卢卡斯快)

添加另一个脚本spawn_protect。嘘

#!/bin/sh

LOG=$1
shift 

nohup $* > $LOG 2>&1  &

并将经理更改为:

public class Runit {
    public static void main(String args[]) throws IOException, InterruptedException {
        Runtime.getRuntime().exec(args);
        while (true) {
            System.out.println("Kill me");
            Thread.sleep(5000);
        }
    }
}
java -classpath jar-with-dependencies.jar temp.exec.Runit spawn_protect.sh /tmp/runit.log runit.sh

现在runit.sh真的脱离了JVM进程!

 类似资料:
  • 我正在使用Javaexec运行bash脚本,但当我进入CTRL C时,Java进程将退出,子进程也将退出,如何在JVM关闭后保持子进程运行? 父母亲上海: 我已经在这里和这里阅读了类似问题的答案,例如,使用nohup在脚本运行命令中启动父bash脚本,或者使用trap命令来阻止信号,在我的研究中,它可以工作,例如“tail-f somefile”,但不适用于我的用例“ffmpeg-params”,

  • 我有一个用PHP编写的守护进程(不是最好的语言,但与我一起工作),它用于从队列接收作业,并在需要完成作业时处理它们。对于每个新作业,我使用pcntl_fork()将作业分叉到子进程中。在这个子进程中,我然后使用proc_open()执行用于音频转码的长时间运行的系统命令,完成后直接返回到子进程。作业完成后,子进程退出并由父进程清理。 为了保持这个守护进程始终运行,我使用upstart。这是我的暴发

  • 我使用Spring Boot Gradle插件启动Tomcat服务器&我的应用程序。我通过启动Tomcat服务器。我还启用了Gradle守护进程,希望能让Gradle构建更快。

  • 要杀死进程,我使用Ctrl+z将程序发送到后台后,通过PID杀死它,这是不会被忽略的。为什么Ctrl+C总是被忽略?我如何解决这个问题?

  • 问题内容: 我有一个派生许多子进程的服务器进程。服务器进程与CPU核心具有关联性,但我不希望该关联性由子进程继承(而是OS应该处理在何处运行这些进程)。有没有办法针对cpu亲和力取消父子进程的链接? 问题答案: 您可以在和之后使用CPU掩码中设置的所有位进行调用。

  • 问题内容: 在Linux中,当我在java.lang.Process对象上运行destroy函数(类型为true的java.lang.UNIXProcess)时,它会发送SIGTERM信号进行处理,有没有办法用SIGKILL杀死它? 问题答案: 不使用纯Java。 你最简单的选择是使用运行的外部进程的命令。 不幸的是,掌握PID并不是那么简单。您将需要使用反射黑魔法来访问该字段,或者弄乱该命令的输