【问题标题】:What to do with unneeded streams from an external process?如何处理来自外部进程的不需要的流?
【发布时间】:2011-01-12 21:18:34
【问题描述】:

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

Executes the specified command and arguments in a separate process.

知道该进程将一直存在到 Java 程序存在之前,我需要如何处理来自该进程的流? (这是一个细节,但 Java 程序会负责终止该进程,并且该进程本身具有内置安全功能,如果它注意到生成他的 Java 程序不再运行,它会在其中杀死自己。

如果我们认为这个过程根本不产生任何输出(例如,因为所有错误消息和 stdout 都被重定向到 /dev/null 并且所有通信都使用 files/sockets/whatever 完成),我需要做什么输入流?

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

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

编辑

基本上,我将 shell 脚本包装在另一个 shell 脚本中,确保将所有内容重定向到 /dev/null。如果我的“外部”shell 脚本(将所有内容重定向到 /dev/null 的脚本)仍然会在 stdoutstderr 上生成任何内容,我很确定我的 Un*x 将不符合要求。然而,令人难以置信的是,在应用程序的生命周期中,我应该以某种方式让线程“白费”地运行。真是令人难以置信。

【问题讨论】:

    标签: java exec stdout stderr


    【解决方案1】:

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

    但是,很少有事情能如此干净利落。从长远来看,为了以防万一,生成一个线程来拉出 stdout/stderr 可能是值得的。有一天它失败并真正推出了一些东西,那是你需要知道结果的那一天。 1 或 2 个线程(我认为只需一个线程就可以完成)不会是很大的开销。尤其是如果您是正确的,并且这些信息流中没有任何结果。

    【讨论】:

    • 有趣。我将编辑我的问题...基本上我将 shell 脚本包装在另一个 shell 脚本中,确保将所有内容重定向到 /dev/null。如果我的“外部”shell 脚本(将所有内容重定向到 */dev/null 的脚本)仍然会在 stdout 上生成任何内容,我很确定我的 Unx 将不兼容i> 或 stderr.
    • @SyntaxT3rr0r - 我明白了。我只是那些偏执的人之一。 :) 我同意额外的线程可能是不必要的。
    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答...不仅仅是我读过它。这是我读过它并且多年来在从 Java 启动外部进程时一直被咬到的问题。所以现在我采取了相当激进的方法。实际上,我只是想到了别的东西:我的“外部”脚本执行“nohup”,生成另一个不受挂断/杀死的脚本,其流与 Java 无关。因此,从 Java 中,我可以在一段时间后读取/关闭/销毁“外部”脚本,因为知道内部脚本对 Java 是不可见的 :)
    • 子进程不一定是Java VM,所以不一定会抛出IOException。例如它可能会收到SIGPIPE
    • @finnw 我不确定你的意思是什么。 JVM 将收到相同的 SIGPIPE 并在收到时抛出 IOException。进程在收到 SIGPIPE 时会做什么取决于它。我相信像 grep 这样的程序如果收到 SIGPIPE 就会退出,但 firefox 或 vlc 不会在意。
    • 只是详尽无遗:我现在正在“nohup”并且还使用“&”进行分叉。
    猜你喜欢
    • 2011-02-22
    • 1970-01-01
    • 2014-11-21
    • 2021-10-29
    • 1970-01-01
    • 2019-02-14
    相关资源
    最近更新 更多