在 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
,它仍然会尊重其他信号,特别是 SIGINT
和 SIGTERM
(Process.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
将在启动其子进程后退出。
使用 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
,它仍然会尊重其他信号,特别是 SIGINT
和 SIGTERM
(Process.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
将在启动其子进程后退出。