如何处理来自外部进程的不需要的流?
当我在单独的进程中执行命令时,例如使用 Runtime.getRuntime().exec(...) 方法,该方法的 JavaDoc 指出:
Executes the specified command and arguments in a separate process.
我需要对来自的流执行什么操作这个进程,知道该进程将一直存在到 Java 程序存在吗? (这是一个细节,但Java程序负责杀死这个进程,并且该进程本身有一个内置的安全性,如果它注意到生成他的Java程序不再运行,它就会杀死自己)。
如果我们认为这个过程根本不产生任何输出(例如,因为所有错误消息和标准输出都被重定向到 /dev/null 并且所有通信都是使用文件/套接字/任何东西完成的),那么我需要对输入流做什么?
我应该让一个(或两个?)Java 线程免费运行,尝试读取 stdout/stderr 吗?
处理从根本不产生 stdout/stderr 的 Java 程序生成的长期存在的外部进程的正确方法是什么?
编辑
基本上,我将 shell 脚本包装在另一个 shell 脚本中,确保将所有内容重定向到 /dev/null。我很确定如果我的“外部”shell 脚本(将所有内容重定向到 /dev/null 的脚本)仍然会在 stdout 或 stderr 上生成任何内容,我的 Un*x 将不合规。然而,我发现令人难以置信的是,我会以某种方式“无缘无故”地在应用程序的生命周期中运行线程。实在令人费解。
When I execute a command in a separate process, for example by using the Runtime.getRuntime().exec(...)
method, whose JavaDoc states:
Executes the specified command and arguments in a separate process.
What do I need to do with the streams from this process, knowing that the process shall live until the Java program exists? (this is a detail but the Java program takes care of killing this process and the process itself has a safety built-in where it kills itself should it notice that the Java program who spawned him his not running anymore).
If we consider that this process produces no output at all (for example because all error messages and stdout are redirected to /dev/null and all communications are done using files/sockets/whatever), what do I need to do with the input stream?
Should I have one (or two?) Java threads running for nothing, trying to read stdout/stderr?
What is the correct way to deal with a long-living external process spawned from a Java program that produces no stdout/stderr at all?
EDIT
Basically I wrap the shell script in another shell script that makes sure to redirect everything to /dev/null. I'm pretty sure my Un*x would be non-compliant if my "outter" shell script (the one redirecting everything to /dev/null) would still generate anything on stdout or stderr. Yet I find it mindboggling that I would somehow be supposed to have threads running during the lifecycle of the app "for nothing". Really boggles the mind.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果一切都如你所说,那么你可能可以忽略它们。
然而,事情很少能如此顺利地进行。从长远来看,生成一个线程来拉取 stdout/stderr 可能是值得的,以防万一。当有一天它失败并真正推出一些东西时,就是你需要知道结果的那一天。 1 或 2 个线程(我认为只用一个线程就可以完成)不会是很大的开销。特别是如果你是正确的并且这些流中没有任何结果。
If everything is as you say, then you can probably ignore them.
However, rarely do things work out so cleanly. It may be worth it in the long run to spawn a single thread to pull stdout/stderr, just in case. The one day it fails and actually puts something out, is the day you needed to know what came out. 1 or 2 threads (I think it could be done with just one) won't be a large overhead. Especially if you are correct and nothing ever comes out of those streams.
我相信,如果您对进程的输入和输出不感兴趣,处理它们的正确方法是立即关闭它们。如果子进程随后尝试分别在 stdin 或 stdout 上调用 read 或 write,则会抛出 IOException。子进程有责任处理它无法读取或写入的事实。
大多数进程会忽略它们无法写入的事实,并默默地丢弃并写入。在 Java 中也是如此,其中 System.out 是一个 PrintWriter,因此 stdout 抛出的任何 IOException 都会被忽略。这几乎就是将输出重定向到 /dev/null 时发生的情况——所有输出都会被默默丢弃。
听起来您已经阅读了有关进程的 API,以及为什么如果进程希望自己进行任何写入或读取,则读取/写入进程很重要。但我要重申,问题是某些操作系统只为(特别是)标准输出分配了非常有限的缓冲区,因此重要的是不要让该缓冲区填满。这意味着要么立即读取子进程的任何输出,要么通知操作系统您不需要该进程的输出,并且它可以释放所持有的任何资源,并拒绝任何进一步写入 stdout 或从 stdin 读取的尝试(而不是而不是仅仅挂起直到资源可用)。
I believe the correct way to deal with a process's input and output if you are not interested in them is to close them promptly. If the child process subsequently tried to call read or write on stdin or stdout respectively, then an IOException would be thrown. It would be the responsibility of the child process to deal with the fact that it cannot read or write.
Most processes will ignore the fact that they cannot write and silently discard and writes. This is true in Java, where System.out is a PrintWriter, so any IOExceptions thrown by stdout are ignored. This is pretty much what happens when you redirect output to /dev/null -- all output is silently discarded.
It sounds like you've read the API on Processes and why it's important to read/write to the process if it expects to be doing any writing or reading of its own. But I'll reiterate, the problem comes that some OSes only allocated very limited buffers for (specifically) stdout, so it is important to either not allow this buffers to fill up. This means either reading any output of the child process promptly, or notifying the OS that you do not require the output of the process and that it can release any resources held, and reject any further attempted to write to stdout or read from stdin (rather than just hanging until resources become available).