2011-11-27 87 views
3

我试图用gpg.exe --passphrase-file my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg(没有--batch和--yes选项)解密。我也提供加密命令,如果有人在意使用它来测试gpg.exe --passphrase-file ..\BE\src\my.passphrase --symmetric --output MTR241_20111124.htm.gpg MTR241_20111124.htmJava进程无法从gpg.exe中捕获InputStream,OutputStream

有两种情况。 情况1:输出目录中不存在MTR241_20111124.htm文件。命令提示符和捕获的exec输出流都会提供相同的输出。

C:\Eclipse\workspace2\sync_inbox>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
Reading passphrase from file descriptor 3 
gpg: CAST5 encrypted data 
gpg: encrypted with 1 passphrase 
gpg: WARNING: message was not integrity protected 

java exec和命令提示符输出相同的messags。

C:\Eclipse\workspace2\sync_inbox>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
inp>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
gpg: CAST5 encrypted data 
gpg: encrypted with 1 passphrase 
gpg: WARNING: message was not integrity protected 

到目前为止不够好

案例2:如果如预期中的命令已经存在的输出文件提示它问我是否要替换。

C:\Eclipse\workspace2\sync_inbox>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
Reading passphrase from file descriptor 3 
gpg: CAST5 encrypted data 
gpg: encrypted with 1 passphrase 
File `MTR241_20111124.htm' exists. Overwrite? (y/N) y 
gpg: WARNING: message was not integrity protected 

但是这个输出是来自java程序,它在第一行之后挂起。它不在控制台上打印任何行。如果我在控制台输入'y',它不接受输入和处理。它只是挂起。我必须手动杀死进程taskkill/F/IM gpg.exe,然后Java控制台程序接受更多命令和进程。

C:\Eclipse\workspace2\sync_inbox>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
inp>gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
gpg.exe --passphrase-file ..\BE\src\my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg 
    --hangs here-- 

当然作品的正常互动命令,说为前:

F:\eclipse\workspace\HTMLProcessor\BEQuery>copy hello.txt world.txt 
inp>copy hello.txt world.txt 
copy hello.txt world.txt 
Overwrite world.txt? (Yes/No/All): y 
inp>y 
y 
     1 file(s) copied. 

因此,这里是我的问题为什么它无法捕捉GPG的输出流,只有当它要求提示是否替换现有的输出文件。

我已经尝试过Runtime.exec(),ProcessBuilder,Plexus-Utils,ExpectJ,Ant在java程序中运行这个gpg.exe,它们都显示相同的结果,无法捕获该进程的输出流特例。我甚至试图编写一个.bat文件来运行gpg --decrypt,但即使如此,它也无法在上述特例中捕获输出流。

我认为它很重要,gpg.exe的起源。那么我得到了它在便携式git分配,在bin文件夹gpg.exe是可用的。

我的问题变得很长而枯燥的,但仍然为那些谁喜欢针砭Java代码

package com.ycs.ezlink.scheduler.cmd; 

import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import org.apache.log4j.Logger; 

public class CmdRunner { 
    private static Logger logger = Logger.getLogger(CmdRunner.class); 

    static class StreamGobbler extends Thread 
    { 
     InputStream is; 
     String type; 

     StreamGobbler(InputStream is, String type) 
     { 
      this.is = is; 
      this.type = type; 
     } 

     public void run() { 
      try { 
       System.out.println("in run!"); 
        System.out.println(type); 
        final byte[] buffer = new byte[1]; 
        for (int length = 0; (length = is.read(buffer)) != -1;) { 
         System.out.write(buffer, 0, length); 
        } 
       } catch (IOException ioe) { 
        ioe.printStackTrace(); 
       } 
     } 
    } 

    public static int process(String cmd){ 
     int exitVal = 0; 
     try { 
      Runtime rt = Runtime.getRuntime(); 
      Process proc = rt.exec(cmd); 
      // any error message? 
      StreamGobbler errorGobbler = new 
       StreamGobbler(proc.getErrorStream(), "ERROR");    

      // any output? 
      StreamGobbler outputGobbler = new 
       StreamGobbler(proc.getInputStream(), "OUTPUT"); 

      // kick them off 
      errorGobbler.start(); 
      outputGobbler.start(); 

      // any error??? 
      System.out.println("Waiting for cmd process to complete "); 
      exitVal = proc.waitFor(); 
      System.out.println("ExitValue: " + exitVal); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }  
     return exitVal; 
    } 

    public static void main(String[] a) throws IOException, InterruptedException, TimeoutException, ExpectJException { 
     String gzipCmd = "gpg.exe --passphrase-file C:/Eclipse/workspace2/BE/src/my.passphrase --decrypt --output C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg"; 
     //CmdRunner.process(gzipCmd); ///--fails 
     //ProcessBuilder pb = new ProcessBuilder("gpg", "--passphrase-file", "C:/Eclipse/workspace2/BE/src/my.passphrase", 
     "--decrypt","--output","C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm", 
     "C:/Eclipse/workspace2/sync_inbox/MTR241_20111124.htm.gpg"); ///--fails 
     ProcessBuilder pb = new ProcessBuilder ("cmd"); 
     pb.redirectErrorStream(true); 
     Process process = pb.start(); 
     OutputStream stdin = process.getOutputStream(); 
     InputStream stderr = process.getErrorStream(); 
     InputStream stdout = process.getInputStream(); 
     StreamGobbler errorGobbler = new StreamGobbler(stderr, "ERROR");    
     errorGobbler.start(); 
     StreamGobbler stdoutGobbler = new StreamGobbler(stdout, "DEBUG");    
     stdoutGobbler.start(); 

     BufferedReader scan = new BufferedReader(new InputStreamReader(System.in)); 
     String line; 
     while ((line = scan.readLine())!= null) { 
       String input = line; 
       System.out.println("inp>"+input); 
       if (input.trim().equals("exit")) { 
        stdin.write("exit\r\n".getBytes()); 
        stdin.flush(); 
        break; 
       } else { 
        stdin.write((input+"\r\n").getBytes()); 
        stdin.flush(); 
       } 
      } 
     System.out.println("exited.."); 
     int returnCode = process.waitFor(); 
     System.out.println(returnCode); 
    } 
} 

最后说一句,如果我使用gpg --batch选项,为y/N输入它没有更多提示,然后它运行顺利。但我只是想知道,为什么会有这个问题。虽然我有一种感觉,gpg.exe最初是为Unix/Linux平台编写的,所以可能会有一些输入输出文件重定向,但我想知道更多关于它的根本原因,以便下次我知道什么时候寻找。

回答

2

您在终端中看到的输出是来自标准输出流,标准错误流和控制台的合并结果。您可以捕获标准输出和标准错误流。但是你不能捕获控制台。这就是为什么gpg 故意直接使用控制台,以防止您捕捉。为什么他们这样做是有争议的。

底线:您将无法捕获直接处理控制台的程序的输入或输出流。

+0

但我注意到,java执行过程可以看到gpg输出,它只是我无法发送任何选择[y/N]输入到gpg。顺便说一句,我刚来了解这个控制台,[http://www.robvanderwoude.com/battech_redirection.php](http://www.robvanderwoude.com/battech_redirection.php)。感谢帮助 –

相关问题