使用 ProcessBuilder
,我一直在尝试创建一个在 JVM 终止时不会终止的独立进程,但似乎没有任何效果。
我已经尝试过 /usr/bin/nohup 命令
,但是当启动它的 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
可能不是您想要的,正如“那个人”所指出的那样; nohup
只会导致进程忽略 SIGHUP
,它仍然会尊重其他信号,特别是 SIGINT
和 SIGTERM
( Process.destroy()
sends a SIGTERM
,例如)。参见 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
将在启动其子进程后退出。
关于java - 在 Java 中创建一个 Nohup 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52394419/