有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么“git pull”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) 个答案

  1. # 1 楼答案

    这是因为SSH密码短语应该从pseudo terminal而不是从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代理正在运行,则所有密钥验证都将传递给该代理
    5. 可能有不同的替代代理实现。一些只是要求用户输入密码以解锁ssh密钥,另一些则在内存中保留一组预解锁的密钥等。根据代理的性质,它可能会在控制台中显示密码提示,或者打开一个带有提示的新单独窗口。查看this page,特别是关于putty/pageant的部分,了解如何在Windows上设置SSH身份验证

    您可以看一下pty4j,它使用JNA实现终端和进程执行的底层内容。或者看看JGit,这是git的纯java重新实现,它根本不调用命令行git。JGit是例如Eclipse Git pluginGerrit Code review system的基础,因此经过精心制作和抛光