【问题标题】:How to handle interactive commands using runtime.getRuntime?如何使用 runtime.getRuntime 处理交互式命令?
【发布时间】:2018-04-06 16:01:42
【问题描述】:

我必须从 Unix 平台上的 Java 程序执行命令。 我正在使用Runtime.getRuntime()

但是,问题是我的命令是交互式的,并且在运行时要求某些参数。例如,命令是createUser。它要求userName 作为运行时。

bash-4.1$ createUser  

Enter the UserName:

如何处理这种情况,以便在运行时从 Java 程序输入用户名?

try {
    Process proc;
    proc = Runtime.getRuntime().exec(cmd, envp);
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

    BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

    // read the output from the command
    String s = null;
    while ((s = stdInput.readLine()) != null) {
        System.out.println(s);
        sb.append(s);
    }

    // read any errors from the attempted command
    while ((s = stdError.readLine()) != null) {
        System.out.println(s);
        sb.append(s);
    }
} catch (Exception e) {
    e.printStackTrace();
    sb = null;
}

听说可以通过expect来实现。但是我如何在 Java 中做到这一点?

【问题讨论】:

  • 我很确定(但不是完全确定)消耗两个输出流需要在不同的线程上完成。另请参阅When Runtime.exec() won't,了解有关正确创建和处理流程的许多好技巧。然后忽略它引用exec 并使用ProcessBuilder 创建进程。还将String arg 拆分为String[] args 以解决包含空格字符的路径之类的问题。

标签: java runtime.exec


【解决方案1】:

还从 proc 中获取标准输出。您在该标准输出中编写的所有内容都转到命令

将用户名发送到standardOutput,不要忘记也发送\n。

【讨论】:

    【解决方案2】:

    您可以检查输入流的最后一行是什么,当您检测到用户输入输入提示时,将您的值写入输出流。

    try {
        Process proc;
        proc = Runtime.getRuntime().exec(cmd, envp);
    
        final BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
    
        final PrintWriter stdOutput = new PrintWriter(proc.getOutputStream());
    
        // read the output from the command
        String s = null;
        while ((s = stdInput.readLine()) != null) {
            System.out.println(s);
    
            if (s.equals("Enter your username")) {
                stdOutput.println("MyUsername");
                stdOutput.flush();
            }
    
            sb.append(s);
        }
    
    } catch (final Exception e) {
        e.printStackTrace();
        sb = null;
    }
    

    (为简单起见删除了错误流)

    请注意,这仅在提示以换行结束时有效。

    如果提示没有新行(例如Username: <cursor here>),您可以尝试在开头写入值:

        ...
        final PrintWriter stdOutput = new PrintWriter(proc.getOutputStream());
        stdOutput.println("MyUsername");
        stdOutput.flush();
        ...
    

    但如果命令清除缓冲区,这将不起作用,在这种情况下(极少数情况)您必须更改从流中读取的方式(例如,读取字节而不是行)

    【讨论】:

    • 出于某种原因,我试图表明您有一个提示不以新行结尾的示例。所以跳过答案的第一部分..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    • 2018-07-08
    • 1970-01-01
    • 2013-02-21
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多