java - 为什么 "git pull"exec 命令卡住并且不打印任何内容?

标签 java git apache-commons apache-commons-exec

执行以下命令时,系统提示我输入密码:

$ git pull
Enter passphrase for key (...)

当我尝试使用 Apache Commons Exec 以编程方式显示相同信息时,程序卡住并且不打印任何内容:

CommandLine cmd = new CommandLine( "git" );
cmd.addArgument( "pull" );
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler( new PumpStreamHandler( System.out, System.err, System.in ) );
executor.execute( cmd );

为什么该示例在没有打印任何内容的情况下卡住了,并且在使用 native 控制台时提示我提供 git 密码?

最佳答案

发生这种情况是因为 SSH 密码应该从伪终端读取,而不是从STDIN读取。您必须在父进程(您的程序)和子进程(git)之间创建一个伪 tty 通信流,并通过该流执行整个通信。看看Pseudo terminal to use with ssh in java得到这个想法。

还应该注意的是,它不是 git 要求输入密码。 git 本身不执行任何身份验证,仅依赖于 ssh (当然,仅适用于存储库,可通过 ssh 访问)。这是操作顺序

  1. git 检测到可以通过 ssh 访问给定存储库并调用 ssh 传输
  2. ssh 传输检测计算机上是否正在运行 ssh 身份验证代理。
  3. 如果未检测到代理(您的情况),则传输会切换到基于控制台的基本身份验证。 ssh 需要一个“真正的控制台”,因此简单的 stdin/stdout 重定向是不够的。
  4. 或者如果 ssh 代理正在运行,则所有 key 验证都会传递给代理。
  5. 可能有不同的替代代理实现。有些只是要求用户输入密码来解锁 ssh key ,其他则在内存中保留一组预先解锁的 key 等。并且根据代理性质,它可能会在控制台中显示密码提示或打开一个带有提示的新单独窗口。检查this page ,特别是有关 putty/pageant 的部分,以了解如何在 Windows 上设置 SSH 身份验证。

您可以看看pty4j它使用 JNA 来实现终端和进程执行低级内容。或者看看JGit这是 git 的纯 java 重新实现,它根本不调用命令行 git。 JGit 是例如 Eclipse Git plugin 的基础或Gerrit Code review system所以它是经过精心设计和打磨的。

关于java - 为什么 "git pull"exec 命令卡住并且不打印任何内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27098082/

相关文章:

java - 互补的泛型类型

java - ftp 文件检索未完成的文件

java - while & for 循环和 JOptionPane 数据输入连接到 for 循环

java - 正则表达式将多个数字与一行中的空格合并

java - 使用 Apache POI 获取 Excel 文件中的列名称

git 标签还没有推送到远程

git - "git merge origin/branch"中忘记斜杠的后果

git - 如何在 SourceTree 中连接到我自己的 Git 服务器?

java - 我需要将哪些 Apache Commons IO jar 添加到我的 Android lib 文件夹中?

maven - 缺少 org.apache.commons.collections.CollectionUtils