Java通过Runtime.exec调用交互式CLI并发送后续命令的问题咨询
问题根源梳理
- 第一次代码问题:每次执行
Runtime.exec()都启动独立的CLI进程,前一次进程的配置仅保存在对应进程的内存中,新启动的进程完全无法复用,因此配置不生效导致登录失败。 - 第二次代码问题:
Runtime.exec()没有向已运行进程发命令的能力,每次调用都会新建进程;同时启动CLI后调用process.waitFor()会阻塞等待CLI进程退出,而交互式CLI默认不会主动终止,因此直接出现无响应卡死。
正确实现方案
你需要启动单次CLI进程后,通过进程的标准输入流写入交互命令,同时主动读取进程的标准输出、错误输出避免缓冲区被占满导致进程阻塞,参考实现代码如下:
Configuration configuration = Configuration.getInstance(); // 启动单次CLI进程 Process process = Runtime.getRuntime().exec(configuration.getCLICommand()); // 单独开线程读取CLI的标准输出,避免缓冲区满阻塞 new Thread(() -> { try (BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; while ((line = stdoutReader.readLine()) != null) { // 可在此处打印日志调试CLI返回内容 System.out.println("CLI输出:" + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 单独开线程读取CLI的错误输出 new Thread(() -> { try (BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { String line; while ((line = stderrReader.readLine()) != null) { System.err.println("CLI错误:" + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 拿到CLI进程的标准输入流,写入命令 try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))) { // 写入配置服务器命令,加换行代表输入完成 writer.write("config -s " + configuration.getPlatformURL() + "\n"); writer.flush(); // 可按需调整等待时长,也可通过解析上方的输出判断命令执行完成,比固定sleep更可靠 Thread.sleep(500); // 写入配置文件命令 writer.write("config -f " + configuration.getPlatformFile() + "\n"); writer.flush(); Thread.sleep(500); // 写入登录命令 writer.write("login " + configuration.getUsername() + " " + configuration.getPass() + "\n"); writer.flush(); Thread.sleep(1000); // 后续有其他操作继续写入即可,所有操作完成后写入退出命令 writer.write("exit\n"); writer.flush(); } catch (InterruptedException | IOException e) { e.printStackTrace(); } // 等待CLI进程执行完成退出 int exitCode = process.waitFor(); System.out.println("CLI执行结束,退出码:" + exitCode);
注意事项
- 命令末尾必须加换行符
\n,交互式CLI是按行识别输入的,没有换行的话CLI会认为命令还没输入完成,一直处于等待状态。 - 必须单独开线程读取CLI的标准输出和错误输出,否则当CLI输出的内容占满系统缓冲区后,CLI进程会被直接阻塞,无法继续执行后续指令。
- 如果需要严格控制命令执行时序,可以在读取输出的线程里增加解析逻辑,匹配到CLI返回的提示符
CLI>后再发送下一条命令,稳定性比固定时长的sleep更高。
内容的提问来源于stack exchange,提问作者Zorak
相关产品推荐
相关产品推荐

