在 Java 中生成一个在 JVM 关闭后仍然存在的进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/295736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:48:20  来源:igfitidea点击:

Spawn a process in Java that survives a JVM shutdown

javaprocess

提问by Jon Skeet

I need to spawn a process in Java (under Linux exclusively) that will continue to run after the JVM has exited. How can I do this?

我需要在 Java 中生成一个进程(仅在 Linux 下),该进程将在 JVM 退出后继续运行。我怎样才能做到这一点?

Basically the Java app should spawn an updater which stops the Java app, updates files and then starts it again.

基本上 Java 应用程序应该产生一个更新程序,它停止 Java 应用程序,更新文件,然后再次启动它。

I'm interested in a hack & slash method to just get it working as well as a better design proposal if you have one :)

我对 hack & slash 方法很感兴趣,只要你有一个更好的设计提案,就可以让它工作:)

回答by Jon Skeet

If you're spawning the process using java.lang.Processit should "just work" - I don't believe the spawned process will die when the JVM exits. You might find that the Ant libraries make it easier for you to control the spawning though.

如果您使用java.lang.Process它生成进程,则它应该“正常工作”-我不相信生成的进程会在 JVM 退出时终止。您可能会发现 Ant 库使您可以更轻松地控制生成。

回答by Jon Skeet

It does actually "just work", unless you're trying to be clever.

它实际上“只是工作”,除非你想变得聪明。

My wrapped java.lang.Process was trying to capture the script's output, so when the JVM died, the script didn't have anywhere to send output so it just dies. If I don't try to capture the output, or the script doesn't generate any or redirects everything to a file or /dev/null, everything works as it should.

我包装的 java.lang.Process 试图捕获脚本的输出,所以当 JVM 死机时,脚本没有任何地方可以发送输出,所以它就死了。如果我不尝试捕获输出,或者脚本不生成任何内容或将所有内容重定向到文件或 /dev/null,则一切正常。

回答by cowls

I was having trouble with this and the launched process was getting killed when the JVM shutdown.

我遇到了这个问题,并且在 JVM 关闭时启动的进程被终止了。

Redirecting stdout and stderr to a file fixed the issue. I guess the process was tied to the launched java app as by default it was expecting to pass its output to it.

将 stdout 和 stderr 重定向到文件修复了该问题。我猜这个过程与启动的 Java 应用程序相关联,因为默认情况下它希望将其输出传递给它。

Here's the code that worked for me (minus exception handling):

这是对我有用的代码(减去异常处理):

ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(logFile);
pb.redirectError(logFile);
Process p = pb.start();

回答by cowls

It won't always "just work". When JVM spawns the child and then shuts down, the child process will also shutdown in some cases. That is expected behaviour of the process. Under WIN32 systems, it just works.

它不会总是“正常工作”。当 JVM 产生子进程然后关闭时,子进程在某些情况下也会关闭。这是过程的预期行为。在WIN32系统下,它只是工作。

E.g. If WebLogic server was started up by a Java process, and then that process exits, it also sends the shutdown signal to the WebLogic via shutdown hook in JVM, which causes WebLogic to also shutdown.

例如,如果WebLogic 服务器是由Java 进程启动的,然后该进程退出,它还会通过JVM 中的关闭钩子向WebLogic 发送关闭信号,从而导致WebLogic 也关闭。

If it "just works" for you then there is no problem, however if you find yourself in a position that child process also shutsdown with JVM it is worth having a look at the "nohup" command. The process won't respond to SIGTERM signal, but will respond to SIGKILL signal, as well as normal operations.

如果它对您“正常工作”,那么没有问题,但是如果您发现自己处于子进程也会与 JVM 一起关闭的位置,那么值得查看“nohup”命令。进程不会响应 SIGTERM 信号,但会响应 SIGKILL 信号,以及正常操作。

Update: The way described above is a bit of an overkill. Another way of doing this would be to use "&" on the end of command. This will spawn a new process that is not a child of current java process.

更新:上述方式有点矫枉过正。另一种方法是在命令末尾使用“&”。这将产生一个新进程,它不是当前 java 进程的子进程。

P.S. Sorry for so many updates, I have been learning and trying it from scratch.

PS 抱歉更新太多,我一直在从头开始学习和尝试。

回答by ernesto

>>don't believe the spawned process will die when the JVM exits.

>> 不要相信 JVM 退出时产生的进程会死亡。

Child process is always dying on my box(SuSE) whenever I kill java. I think, the child process will die if it's dealing with I/O of the parent process(i.e., java)

每当我杀死 java 时,子进程总是在我的盒子(SuSE)上死亡。我认为,如果子进程处理父进程(即java)的I/O,它就会死

回答by Dashogun

I thought the whole point of Java was that it's fully contained within the JVM. It's kinda hard to run bytecode when there's no runtime.

我认为 Java 的全部意义在于它完全包含在 JVM 中。当没有运行时,运行字节码有点困难。

If you're looking to have a totally separate process you might look into trying to start a second java.exe instance. Although for your application, it might be easier to simply make a synchronized block that stops (but doesn't kill) your app, does the updating, and then re-initializes your app's data.

如果您希望拥有一个完全独立的进程,您可能会考虑尝试启动第二个 java.exe 实例。尽管对于您的应用程序,简单地制作一个同步块来停止(但不会终止)您的应用程序,进行更新,然后重新初始化您的应用程序数据可能会更容易。

回答by rmeador

If you're looking at making an updater on Linux, you're probably barking up the wrong tree. I believe all major linux distros have a package manager built in. You should use the package manager to do your updating. Nothing frustrates me more than programs that try to self-update... (I'm looking at you, Eclipse)

如果您正在考虑在 Linux 上制作更新程序,那么您可能找错了树。我相信所有主要的 linux 发行版都有一个内置的包管理器。你应该使用包管理器来进行更新。没有什么比尝试自我更新的程序更让我沮丧的了......(我在看着你,Eclipse)