为什么" git pull" exec命令卡住并打印什么?

时间:2014-11-24 04:53:29

标签: 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 );

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

1 个答案:

答案 0 :(得分:2)

这是因为SSH密码短语应该从pseudo terminal而非STDIN读取。您必须在父(您的程序)和子(git)进程之间创建伪tty通信流,并通过该流执行整个通信。看一下Pseudo terminal to use with ssh in java来了解这个想法。

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

  1. git检测到可以通过ssh访问给定的存储库并调用ssh transport
  2. ssh transport检测ssh身份验证代理是否在计算机上运行。
  3. 如果未检测到代理(您的情况),则传输将切换到基于控制台的基本身份验证。 ssh期望一个“真正的控制台”,所以简单的stdin / stdout重定向是不够的。
  4. 或者如果ssh代理正在运行,则所有密钥验证都将传递给代理。
  5. 可能有不同的替代代理实现。有些人只是要求用户输入密码来解锁ssh密钥,其他人则将一组预先解锁的密钥保存在内存中等等。根据代理性质,它可能会在控制台中显示密码提示或打开一个带有提示的新单独窗口。检查this page,特别是有关putty / pageant的部分,以了解如何在Windows上设置SSH身份验证。
  6. 您可以查看pty4j,它使用JNA来实现终端和流程执行低级别的东西。或者看看JGit这是git的纯java重新实现,它根本不会调用命令行git。 JGit是例如Eclipse Git pluginGerrit Code review system的基础,因此它经过精心设计和完善。