Java调用GitHub CLI的gh auth login --with-token命令失败求助
解决Java ProcessBuilder调用GitHub CLI认证挂起的问题
问题原因
你在命令行里用的< C:\path\to\my\github-api-token.txt是Windows shell的输入重定向语法,但ProcessBuilder是直接调用gh.exe程序,不会解析shell的特殊语法。当你把<和文件路径作为参数传给gh时,gh会认为你需要手动输入token,一直等待标准输入,导致进程挂起。
解决方案
手动处理输入流,将token文件的内容写入gh进程的标准输入,同时要单独读取进程的输出和错误流(避免缓冲区溢出导致挂起)。
示例代码
import java.io.File; import java.io.FileInputStream; import java.io.OutputStream; import java.io.IOException; public class GhAuthHandler { public static void main(String[] args) { try { // 构建gh认证命令,注意不要加<和文件路径参数 ProcessBuilder pb = new ProcessBuilder("gh", "auth", "login", "--with-token"); Process process = pb.start(); // 将token文件内容写入进程标准输入 try (FileInputStream tokenInput = new FileInputStream("C:\\path\\to\\my\\github-api-token.txt"); OutputStream processInput = process.getOutputStream()) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = tokenInput.read(buffer)) != -1) { processInput.write(buffer, 0, bytesRead); } processInput.flush(); // 关闭输入流,告诉gh输入已完成 processInput.close(); } // 启动线程读取标准输出,防止缓冲区满导致进程阻塞 new Thread(() -> { try (var reader = new java.io.BufferedReader( new java.io.InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println("GH输出: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 启动线程读取错误输出 new Thread(() -> { try (var reader = new java.io.BufferedReader( new java.io.InputStreamReader(process.getErrorStream()))) { String line; while ((line = reader.readLine()) != null) { System.err.println("GH错误: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); // 等待进程完成并获取退出码 int exitCode = process.waitFor(); System.out.println("认证进程退出码: " + exitCode); // 可选:验证登录状态 if (exitCode == 0) { Process statusProcess = new ProcessBuilder("gh", "auth", "status").start(); // 同样处理状态查询的输出流 new Thread(() -> { try (var reader = new java.io.BufferedReader( new java.io.InputStreamReader(statusProcess.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println("登录状态: " + line); } } catch (IOException e) { e.printStackTrace(); } }).start(); statusProcess.waitFor(); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }
关键注意点
- 不要传递shell重定向参数:
<和文件路径不是gh命令的参数,是shell的语法,ProcessBuilder不支持,必须自己处理输入。 - 关闭进程的标准输入流:写完token后一定要关闭
OutputStream,否则gh会一直等待更多输入,导致挂起。 - 必须读取输出和错误流:Java进程的标准输出/错误流有缓冲区限制,如果不及时读取,缓冲区满了会导致gh进程阻塞,无法继续执行。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

