【问题标题】:Java: read input prompt from terminalJava:从终端读取输入提示
【发布时间】:2014-10-23 04:10:52
【问题描述】:

我正在用 Java 创建一个在 Linux 中运行 ssh-keygen 的进程。该实用程序通常从终端获取用户输入,因此我需要从我的 Java 程序中发送响应。以下是在this question 的帮助下创建的相关代码:

// Create a process to run ssh-keygen.
ProcessBuilder procBuilder = new ProcessBuilder("ssh-keygen", "-t", "rsa");
// Redirect errors to the process' standard output.
procBuilder.redirectErrorStream(true);
Process proc = procBuilder.start();

Scanner fromProc = new Scanner(new InputStreamReader(proc.getInputStream()));
OutputStream toProc = proc.getOutputStream();

// While there is another line of output from the process. GETS STUCK HERE.
while (fromProc.hasNextLine()) {
    String message = fromProc.nextLine();
    // If the process asks to overwrite existing keys.
    if (message.startsWith("Overwrite (y/n)?") == true) {
        // Send response to overwrite RSA keys.
        toProc.write("y\n".getBytes());
        toProc.flush();
    }
    // If the message asks to enter a passphrase or specify a file.
    else if (message.startsWith("Enter")) {
        // Send response to use the default.
        toProc.write("\n".getBytes());
        toProc.flush();
    }
}

现在是问题,以及为什么我之前链接的问题不足。当 ssh-keygen 要求用户输入时,这似乎卡在 fromProc.hasNextLine() 上。我怀疑这是因为要求用户输入的行不以换行符结尾(因为直接输入终端的响应会与提示出现在同一行)。

所以这是我的问题。如果提示行不以换行符结尾,我该如何阅读?我想我也许可以使用 fromProc.useDelimiter() 来替代换行符,但我不完全确定是什么,因为提示往往只是以空格结尾。

或者,是否可以使用 bash 脚本更轻松地完成此操作?不幸的是,我对 bash 的经验很少,我不确定当 ssh-keygen 的提示每次都不同时是否可以模拟用户输入。我在此处的 Java 代码旨在灵活,因为它仅在某些提示出现时才响应。

免责声明:这只会在具有非常具体系统细节的已知机器上运行。它是有效的嵌入式代码,所以我不需要担心可移植性。

【问题讨论】:

    标签: java linux


    【解决方案1】:

    要扫描没有行尾的短语,您可能应该使用Scanner.findInLine

    但是,我认为您的麻烦不会就此结束。 ssh-keygen 将一些提示输出到其关联的 tty(并期望从那里得到答案),而不是标准输出和标准输入。事实上,我只是出于好奇测试了它,它在标准错误上给出一个提示,在标准输出上给出一个提示,然后在 tty 上给出下一个提示。

    您为什么不避免所有这些,将文件名、密码和所有这些作为参数传递给 ssh-keygen 命令?

    你可以在this answer看到如何。

    【讨论】:

    • 这很有效,谢谢,尽管我确实需要将 "y\n".getBytes() 传递给进程以处理请求覆盖提示。