2011-01-14 18 views
11

Apache Commons Exec ile başlatılan bir komutun stdinine bir metin argümanı pipetlemem gerekiyor (meraklı için, komut gpg'dir ve argüman anahtar deponun paroladır; gpg'nin parolayı açıkça belirtmek için bir argümanı yoktur. sadece bunu stdin'den kabul etmek için). Apache Commons Exec ile başlatılan bir yürütülebilir dosyaya bir dize argümanı nasıl verilir?

Ayrıca, hem Linux hem de Windows'u desteklemek için buna ihtiyacım var. Bir kabuk komut dosyası olarak

yapardım

cat mypassphrase|gpg --passphrase-fd 

veya

type mypassphrase|gpg --passphrase-fd 

ama (cmd yorumlanır yürütülebilir ancak komuta yerleşik bir komut olmasın da tip Windows üzerinde çalışmıyor .exe). (Aşağıdaki nedenden dolayı) kodunun (yukarıdaki nedenden) sorumlu olmadığı

. Bunun için tüm bir kabuğu yumurtlamak çok çirkin, daha zarif bir çözüm arıyordum. Ne yazık ki, BouncyCastle kütüphanesi ve PGP arasında bazı uyumsuzluk sorunları var, bu yüzden (çok kısa) zamanımda tamamen programlı bir çözüm kullanamıyorum.

Şimdiden teşekkürler. gpg komut kabul etmeyeceğim çünkü

CommandLine cmdLine = new CommandLine("type"); 
cmdLine.addArgument(passphrase); 
cmdLine.addArgument("|"); 
cmdLine.addArgument("gpg"); 
cmdLine.addArgument("--passphrase-fd"); 
cmdLine.addArgument("0"); 
cmdLine.addArgument("--no-default-keyring"); 
cmdLine.addArgument("--keyring"); 
cmdLine.addArgument("${publicRingPath}"); 
cmdLine.addArgument("--secret-keyring"); 
cmdLine.addArgument("${secretRingPath}"); 
cmdLine.addArgument("--sign"); 
cmdLine.addArgument("--encrypt"); 
cmdLine.addArgument("-r"); 
cmdLine.addArgument("recipientName"); 
cmdLine.setSubstitutionMap(map); 
DefaultExecutor executor = new DefaultExecutor(); 
int exitValue = executor.execute(cmdLine); 

cevap

17

Bir boru argüman (|) ekleyemezsiniz. Boruyu yorumlayan ve bu komut satırını kabuğa yazdığınızda özel işlem yapan kabuk (ör. bash).

elle bir komutun standart girdisine veri göndermek için ByteArrayInputStream kullanabilirsiniz (bash yaptığı gibi o | gördüğünde).

Executor exec = new DefaultExecutor(); 

    CommandLine cl = new CommandLine("sed"); 
      cl.addArgument("s/hello/goodbye/"); 

    String text = "hello"; 
    ByteArrayInputStream input = 
     new ByteArrayInputStream(text.getBytes("ISO-8859-1")); 
    ByteArrayOutputStream output = new ByteArrayOutputStream(); 

    exec.setStreamHandler(new PumpStreamHandler(output, null, input)); 
    exec.execute(cl); 

    System.out.println("result: " + output.toString("ISO-8859-1")); 

Bu

(olsa UTF-8, daha fazla uygun kodlama olabilir) ( bash) kabuk içine echo "hello" | sed s/hello/goodbye/ yazarak eşdeğer olmalıdır.

+0

Çok güzel cevabı: önceden bash uğramadan https://github.com/Macilias/Utils/blob/master/ShellUtils.java

temelde daha önce burada gösterildiği gibi boru kullanımını simüle edebilirsiniz ! Günümü kurtardım! – BetaRide

0

Merhaba ben böyle küçük bir yardımcı sınıf kullanacak bunu:

public static String runCommand(String command, Optional<File> dir) throws IOException { 
    String[] commands = command.split("\\|"); 
    ByteArrayOutputStream output = null; 
    for (String cmd : commands) { 
     output = runSubCommand(output != null ? new ByteArrayInputStream(output.toByteArray()) : null, cmd.trim(), dir); 
    } 
    return output != null ? output.toString() : null; 
} 

private static ByteArrayOutputStream runSubCommand(ByteArrayInputStream input, String command, Optional<File> dir) throws IOException { 
    final ByteArrayOutputStream output = new ByteArrayOutputStream(); 
    CommandLine cmd = CommandLine.parse(command); 
    DefaultExecutor exec = new DefaultExecutor(); 
    if (dir.isPresent()) { 
     exec.setWorkingDirectory(dir.get()); 
    } 
    PumpStreamHandler streamHandler = new PumpStreamHandler(output, output, input); 
    exec.setStreamHandler(streamHandler); 
    exec.execute(cmd); 
    return output; 
} 
İlgili konular