2011-01-14 3 views
11

Apache Commons Exec으로 시작한 명령의 표준 입력란에 텍스트 인수를 파이프해야합니다. (호기심에 대한 명령은 gpg이고 인수는 키 저장소에 대한 암호이며 gpg에는 암호를 명시 적으로 제공하는 인수가 없습니다 , 단지 표준에서 그것을 받아들이는).Apache Commons Exec에서 실행되는 실행 파일에 문자열 인수를 파이프하는 방법은 무엇입니까?

또한 Linux와 Windows를 모두 지원해야합니다. 쉘 스크립트에서

내가 할 줄

cat mypassphrase|gpg --passphrase-fd 

또는

type mypassphrase|gpg --passphrase-fd 

있지만 (cmd를 해석 실행하지만, 명령에 내장 된 명령이 아니다으로 유형은 Windows에서 작동하지 않습니다 .exe).

코드이 작동하지 않습니다 (위의 이유로). 이것을 위해 전체 셸을 생성하는 것은 너무 추합니다. 좀 더 우아한 해결책을 찾고있었습니다. 불행히도 BouncyCastle 라이브러리와 PGP 간에는 몇 가지 비호 환성 문제가 있으므로 (매우 짧은 시간에) 완전히 프로그래밍 방식의 솔루션을 사용할 수는 없습니다.

미리 감사드립니다. gpg 명령을 받아 들일 수 없기 때문에

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); 

답변

17

당신은 파이프 인수 (|)를 추가 할 수 없습니다. 파이프를 해석하는 쉘 (예 : bash)이며 쉘에 해당 명령 행을 입력 할 때 특수 처리를 수행합니다.

ByteArrayInputStream을 사용하여 수동으로 명령의 표준 입력으로 데이터를 보낼 수 있습니다 (을 볼 때 bash과 비슷 함).

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")); 

은 (비록 UTF-8이 더 적합한 부호화 될 수있는) ( bash) 쉘로 echo "hello" | sed s/hello/goodbye/ 입력에 상응해야한다.

+0

아주 좋은 대답을 : 미리 떠들썩한 파티를 호출하지 않고 https://github.com/Macilias/Utils/blob/master/ShellUtils.java

는 기본적으로보다 전에 여기에 표시된 같은 파이프 사용을 시뮬레이션 할 수 있습니다 ! 나의 날을 구했다! – BetaRide

0

안녕하세요이 같은 작은 헬퍼 클래스 사용이 작업을 수행합니다 :

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; 
}