在 Java 中创建一个 Nohup 进程

Creating a Nohup Process in Java

使用 ProcessBuilder,我一直在尝试创建一个在 JVM 终止时不会终止的独立进程,但似乎没有任何效果。

我试过 /usr/bin/nohup commands,但是当启动它的 JVM 终止时,它似乎仍然终止。在 Java?

中有什么方法可以做到这一点吗?

好吧,首先让我们编写一个测试脚本来验证您所看到的内容:

$ cat /tmp/test.sh 
#!/bin/bash

for sig in SIGINT SIGTERM SIGHUP; do
  trap "echo Caught $sig" $sig
done

echo Traps registered, sleeping
sleep 10
echo Done sleeping, exiting

当我通过以下方式调用它时:

new ProcessBuilder("/tmp/test.sh").inheritIO().start().waitFor(1, TimeUnit.SECONDS);

我看到 Java 进程在 1 秒后终止(因为 waitFor() 超时),但是子进程 继续运行 Done sleeping 消息在 JVM 退出后打印到控制台)。这与 this question.

中讨论的内容一致

所以我建议做的第一件事是验证您最初的假设,即子进程实际上正在被杀死;也许其他原因导致它因其他原因而死亡。使用 .inheritIO() 可以帮助调试,以防子进程生成您没有看到的错误消息。


综上所述,nohup 可能不是您想要的,如 'that other guy' 所述; nohup 只会导致进程忽略 SIGHUP,它仍然会尊重其他信号,特别是 SIGINTSIGTERMProcess.destroy() sends a SIGTERM, for instance). See this question 更多.

与编程中的所有问题一样,引入更多层可能会有所帮助:)

创建一个 shell 脚本来处理所需的拒绝逻辑,例如

$ cat start-and-disconnect.sh
#!/bin/bash

# obviously tweak this as necessary to get the behavior you want,
# such as redirecting output or using disown instead of nohup
nohup "$@" & 

这里的优点是 Bash(或任何你喜欢的 shell)比 Java 有更好的进程管理控制,现在你可以单独测试它,而不需要编译和 运行 你的 Java 应用程序。

一旦您对脚本感到满意,您的 Java 代码就会变成:

new ProcessBuilder("/path/to/start-and-disconnect.sh", "/path/to/your_binary.sh")
    .inheritIO().start().waitFor();

您可以安全地 .waitFor() 完成调用,因为 start-and-disconnect.sh 将在启动其子进程后退出。