我需要将一个文本参数传递给使用Apache Commons Exec启动的命令的stdin(对于好奇,命令是gpg,参数是密钥库的密码; gpg没有提供密码的参数明确地,只从stdin接受它。
此外,我需要它来支持Linux和Windows。
在shell脚本中我会做
cat mypassphrase|gpg --passphrase-fd
或
type mypassphrase|gpg --passphrase-fd
但是类型在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);
答案 0 :(得分:17)
您无法添加管道参数(|
),因为gpg
命令不接受该参数。它是shell(例如bash
)解释管道并在您将命令行键入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"));
这应该等同于在{(1 {}})shell中键入echo "hello" | sed s/hello/goodbye/
(尽管UTF-8可能是更合适的编码)。
答案 1 :(得分: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;
}