簡體   English   中英

Java進程無法從gpg.exe捕獲InputStream,OutputStream

[英]Java process cannot capture InputStream, OutputStream from gpg.exe

我正在嘗試使用gpg.exe --passphrase-file my.passphrase --decrypt --output MTR241_20111124.htm MTR241_20111124.htm.gpg解密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.htm

有兩種情況。 情況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和命令提示符會打印相同的消息。

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平台編寫的,所以可能會有一些輸入輸出文件重定向,但我想了解更多關於它的根本原因,以便下次我知道什么尋找。

您在終端中看到的輸出是標准輸出流,標准錯誤流和控制台的合並結果。 您可以捕獲標准輸出和標准錯誤流。 但你無法捕獲控制台。 這就是為什么gpg 故意直接使用控制台,以防止你捕獲。 為什么他們這樣做是有爭議的。

結論:您將無法捕獲直接處理控制台的程序的輸入或輸出流。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM