如何处理来自外部进程的不需要的流?

时间:2011-01-12 21:18:35

标签: java exec stdout stderr

当我在一个单独的进程中执行命令时,例如使用其JavaDoc声明的Runtime.getRuntime().exec(...)方法:

Executes the specified command and arguments in a separate process.

我需要对此进程中的流做什么,知道该进程应该存在直到Java程序存在? (这是一个细节,但Java程序负责杀死这个过程,并且该过程本身具有内置的安全性,如果它注意到生成他的Java程序不再运行它就会自杀它。)

如果我们认为这个过程根本不产生输出(例如因为所有错误消息和stdout被重定向到/ dev / null并且所有通信都是使用文件/套接字/其他来完成的),我需要做什么输入流?

我是否应该只运行一个(或两个?)Java线程,尝试读取stdout / stderr?

处理从不产生stdout / stderr的Java程序产生的长期外部进程的正确方法是什么?

修改

基本上我将shell脚本包装在另一个shell脚本中,该脚本确保将所有内容重定向到 / dev / null 。如果我的“outter”shell脚本(将所有内容重定向到/ dev / null)仍然会在 stdout stderr上生成任何内容,我很确定我的Un * x将不合规。然而,我发现令人难以置信的是,我会以某种方式在应用程序的生命周期中“无所事事”地运行线程。真的很难以理解。

2 个答案:

答案 0 :(得分:1)

如果一切如你所说,那么你可能会忽略它们。

然而,很少做得如此干净。从长远来看,为了以防万一,产生单个线程来拉取stdout / stderr可能是值得的。有一天它失败并实际上放了一些东西,那就是你需要知道什么出来的那一天。 1或2个线程(我认为它只能用一个完成)不会是一个很大的开销。特别是如果你是正确的,没有任何东西从这些流中出来。

答案 1 :(得分:1)

如果您对进程的输入和输出不感兴趣,我认为正确的方法是立即关闭它们。如果子进程随后分别尝试在stdin或stdout上调用read或write,则会抛出IOException。儿童进程有责任处理它无法读写的事实。

大多数进程都会忽略它们无法写入并静默丢弃和写入的事实。在Java中也是如此,其中System.out是PrintWriter,因此将忽略stdout抛出的任何IOExceptions。这几乎是将输出重定向到/ dev / null时发生的事情 - 所有输出都被静默丢弃。

听起来你已经阅读了关于进程的API以及为什么读取/写入进程的重要性,如果它希望进行任何自己的写入或读取。但我要重申,问题在于某些操作系统只为(特别是)stdout分配了非常有限的缓冲区,因此不允许这个缓冲区填满是很重要的。这意味着要么及时读取子进程的任何输出,要么通知操作系统您不需要输出进程,并且它可以释放任何保留的资源,并拒绝任何进一步尝试写入stdout或从stdin读取(而不是而不只是悬挂,直到资源可用)。