【问题标题】:Java stuck in infinite loop executing a wmic command on Windows Server 2003Java 陷入无限循环,在 Windows Server 2003 上执行 wmic 命令
【发布时间】:2012-11-13 19:38:23
【问题描述】:

我正在尝试获取 Windows Server 2003 机器上正在运行的进程及其文件路径的列表。我正在使用以下代码来尝试这样做:

protected Map<String,String> getProcesses() {
    Map<String,String> processes = new HashMap<String,String>();
    try {
        String line;
        Process p = null;

        // Windows
        if (OS.indexOf("win") >= 0) {
            p = Runtime.getRuntime().exec("wmic process get description,executablepath");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            LOG.info("Entering while loop");
            while ((line = input.readLine()) != null) {
                LOG.info("blah");
                String[] array = line.split("\\s+");
                if (array.length > 1) {
                    processes.put(array[0], array[1]);
                }
            }
            LOG.info("Exited while loop");
            input.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return processes;
}

程序在 while 条件下陷入无限循环。 “blah”和“Exited while loop”永远不会输出到日志中。我已经在我的 win7 本地计算机和输出信息的服务器上的命令提示符下运行了该命令。我还在我的本地机器上运行了上面的代码,它也可以正常工作。看起来这是 Java 和 Windows Server 2003 之间的一些问题,我在过去 3 小时的谷歌搜索中无法找到。任何帮助将不胜感激。

【问题讨论】:

    标签: java windows windows-server-2003


    【解决方案1】:

    在获取和使用您的InputStream 之前,您需要获取并关闭您的OutputStream。这将向进程确认您已开始向进程发送输入(在本例中为无输入)。

    p.getOutputStream().close();
    

    请记住,在Process 对象上,getInputStream() 输入来自进程的输出流,getOutputStream() 输出进入进程的输入流。

    【讨论】:

    • 嗯,我会试试p.getOutputStream().close(); BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); 看看有什么作用。我会尽快报告。
    • 在 3 小时的挠头后,您的回答解决了我的问题。我将把它称为 wmic 中的错误,但我会解决这个问题。谢谢!!奇怪的是,如果您将 wmic 输出重定向到文件并且不关闭输出流,它就会起作用。这不仅仅是一个java问题。我在 vbscript 测试用例中遇到了同样的问题。
    • 针对 Windows XP 测试 Java 应用程序并面临同样的问题。我尝试了许多不同的技术来修复死锁,包括消耗标准错误、写入缓冲区。这篇文章修复了它。非常感谢。
    【解决方案2】:

    记住BufferedReader.readLine() 操作将在输入结束时阻塞,参见here

    我认为API for Process 中解释了您所遇到的情况:

    创建进程的方法可能不适用于某些本机平台上的特殊进程,例如本机窗口进程、守护进程、Microsoft Windows 上的 Win16/DOS 进程或 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准io(即stdin、stdout、stderr)操作都会通过三个流(getOutputStream()、getInputStream()、getErrorStream())重定向到父进程。父进程使用这些流向子进程提供输入并从子进程获取输出。由于部分原生平台只为标准输入输出流提供有限的缓冲区大小,未能及时写入子进程的输入流或读取输出流可能导致子进程阻塞,甚至死锁。

    【讨论】:

    • 所以也许当我在服务器上运行它时,进程数在我可以读取之前溢出缓冲区?
    • 有可能。我不熟悉 wmic 命令,所以我不能确定是这种情况。此外,@rgettman 是对的,您应该阅读流程 OutputStream。
    猜你喜欢
    • 1970-01-01
    • 2020-02-09
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 2020-05-13
    相关资源
    最近更新 更多