我有以下代码来执行Openssl命令并通过Java运行时读取该命令产生的输出
public void executeCmd() throws IOException {
Runtime rt = Runtime.getRuntime();
String[] commands = new String[]{"openssl", "rsa", "-noout", "-modules", "-in", "myPathToKeyFile", "|", "openssl", "sha256"};
Process proc = rt.exec(commands);
BufferedReader stdInKey = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String s = null;
while ((s = stdInKey.readLine()) != null) {
System.out.println(s);
}
}
当我通过Cmd运行命令时,它正在工作,我能够看到输出
但是当我运行这段代码时,出现以下错误:
Exception in thread "main" java.io.IOException: Cannot run program "openssl": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:620)
at java.lang.Runtime.exec(Runtime.java:485)
at com.renault.vnext.business.impl.CmdRunner.executeCmd(CmdRunner.java:22)
at com.renault.vnext.business.impl.CmdRunner.main(CmdRunner.java:10)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:444)
at java.lang.ProcessImpl.start(ProcessImpl.java:140)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 4 more
注意:我已经在路径变量中设置了upto bin文件夹
我能够在cmd中运行命令并获取输出。我的要求是从命令ouptut中获取标准输入值
非常感谢您的帮助!
答案 0 :(得分:1)
首先,您显然在PATH环境变量的任何目录中都没有AttributeError: 'LegendItem' object has no attribute 'setColumnCount'
。更改PATH以包括包含openssl可执行文件的目录,或者更改代码以指定openssl可执行文件的完整路径名(因此它不需要使用PATH)。如果在Windows上,请注意,您可以在单个进程中或在注册表中全局更改PATH。在后一种情况下,您需要使用PATH 重新创建任何进程,例如“命令”窗口,终端,shell,powershell或IDE。将Java exec can't run program, error = 2和CreateProcess error=2, The system cannot find the file specified复制。
第二,您拼错了openssl[.exe]
。
第三,将-modulus
之类的重定向传递为"|",etc
的参数将不起作用。当您在Unix中的shell或Windows中的命令提示符下键入openssl
时,不会将openssl rsa ... | openssl sha256
传递给第一个openssl。相反,它运行两个不同的进程,并将第一个的输出重定向到管道,第二个的输入从该管道重定向。 | openssl sha256
不是命令处理器,不能执行此操作。您可以:
仅运行Runtime.exec()
部分,在Java代码中读取输出,并在Java中执行该输出的SHA256
运行命令解释器,并告诉 it 执行复合命令openssl rsa
(全部作为一个字符串)。在Unix上,请使用适当的外壳程序-该外壳程序可能会因您的系统而异,但是openssl rsa ... | openssl sha256
很常见。在Windows上,请使用/bin/sh -c
。
仅供参考,如果您拥有或获得BouncyCastle库,它们可以直接在Java中直接使用Java来读取cmd.exe /c
可以读取的相同文件,提取模数和格式并对其进行哈希处理,而无需使用openssl rsa
。但是您没有问这个,所以在Stack上不是答案。
答案 1 :(得分:1)
我的系统是Windows 10 x64,因此也许您必须调整openssl.exe的路径。
开始解决方案路径我首先运行OpenSSL命令行:
openssl rsa -noout -modulus -in keyunencrypted.pem | openssl sha256
此结果作为参考:
(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f
请注意,我使用的是“ 模量”,而不是命令字符串中的“ 模块”。
开始Java体验,我了解到opensll命令行在shell中运行,但是在运行时却没有 通过Runtime.exec的OpenSSL。因此,有一种方法可以通过Output-> InputStream将完整的命令行拆分为两个单独的命令。在Apache的common-io-library的帮助下,有一个非常简单的解决方案。您从https://mvnrepository.com/artifact/commons-io/commons-io获取库,并且 我使用2.7版进行测试。
以下示例摘自https://stackoverflow.com/a/7226858/8166854,由用户@Bohemian编写,并给出以下结果:
[(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f]
这应该是预期的结果,并且只需一点点字符串格式即可获得所需的内容。
这是源代码,请记住没有适当的异常处理。
import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class MainSo {
public static void main(String[] args) throws IOException {
System.out.println("https://stackoverflow.com/questions/63177584/java-error-in-executing-openssl-command-thorugh-runtime/63182609#63182609");
String[] commands1 = new String[]{"E:\\intellij_projects\\openssl_1_1_1g-win64-mingw\\openssl.exe",
"rsa", "-noout", "-modulus", "-in", "keyunencrypted.pem"};
String[] commands2 = new String[]{"E:\\intellij_projects\\openssl_1_1_1g-win64-mingw\\openssl.exe", "sha256"};
// https://stackoverflow.com/a/7226858/8166854
// by @Bohemian
// you need https://mvnrepository.com/artifact/commons-io/commons-io
// commons-io-2.7.jar
Process p1 = Runtime.getRuntime().exec(commands1);
InputStream input = p1.getInputStream();
Process p2 = Runtime.getRuntime().exec(commands2);
OutputStream output = p2.getOutputStream();
IOUtils.copy(input, output);
output.close(); // signals command2 to finish
List<String> result = IOUtils.readLines(p2.getInputStream(), StandardCharsets.UTF_8);
System.out.println(result);
}
}