11

我需要将一个文本参数传递给使用 Apache Commons Exec 启动的命令的标准输入(出于好奇,命令是 gpg,参数是密钥库的密码;gpg 没有明确提供密码的参数,只有从标准输入接受它)。

另外,我需要它来支持 Linux 和 Windows。

在一个shell脚本中我会做

cat mypassphrase|gpg --passphrase-fd

或者

type mypassphrase|gpg --passphrase-fd

但是 type 在 Windows 上不起作用,因为它不是可执行文件,而是内置在命令解释 (cmd.exe) 中的命令。

代码不起作用(由于上述原因)如下。为此生成一个完整的外壳太难看了,我一直在寻找更优雅的解决方案。不幸的是,BouncyCastle 库和 PGP 之间存在一些不兼容问题,因此我无法在(非常短的)时间内使用完全编程的解决方案。

提前致谢。

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

2 回答 2

17

您不能添加管道参数 ( |),因为该gpg命令不会接受它。bash当您在 shell 中键入命令行时,解释管道并进行特殊处理的是 shell(例如)。

您可以使用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"));

这应该相当于输入echo "hello" | sed s/hello/goodbye/( bash) shell(尽管 UTF-8 可能是更合适的编码)。

于 2011-01-20T20:02:47.220 回答
0

嗨,要做到这一点,我将使用一个像这样的小助手类:https ://github.com/Macilias/Utils/blob/master/ShellUtils.java

基本上,您可以在不事先调用 bash 的情况下模拟此处所示的管道使用情况:

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;
}
于 2016-10-17T16:02:53.387 回答