Java - 在运行时执行 OpenSSL 命令时出错
Java - Error in executing OpenSSL command thorugh Runtime
我有以下代码来执行 Openssl 命令并通过 Java Runtime
读取命令产生的输出
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
注意:我已经在路径变量中设置了 bin 文件夹
我能够 运行 在 cmd 中执行命令并获得输出。我的要求是从命令 ouptut
中获取标准输入值
非常感谢您的帮助!
首先,您显然在 PATH 环境变量的任何目录中都没有 openssl[.exe]
。要么更改您的 PATH 以包括包含 openssl 可执行文件的目录,要么更改您的代码以指定 openssl 可执行文件的完整路径名(因此它不需要使用 PATH)。如果在 Windows 上,请注意您可以在单个进程中或在注册表中全局更改 PATH;在后一种情况下,您需要 重新创建 使用 PATH 的任何进程,例如您的 'command' window、终端、shell、电源shell,或 IDE。欺骗 Java exec can't run program, error = 2 and CreateProcess error=2, The system cannot find the file specified .
其次,您拼写错误 -modulus
。
第三,将像 "|",etc
这样的重定向作为参数传递给 openssl
是行不通的。当您在 Unix 中向 shell 或 Windows 中的命令提示符键入 openssl rsa ... | openssl sha256
时,不会将 | openssl sha256
传递给第一个 openssl;相反,它 运行 是两个不同的进程,并将第一个进程的输出重定向到一个管道,并将第二个进程的输入重定向到该管道。 Runtime.exec()
不是命令处理器,不能执行此操作。您可以:
运行 仅 openssl rsa
部分,读取 Java 代码中的输出,并在 Java[ 中对该输出执行 SHA256 =24=]
运行一个命令解释器并告诉它执行复合命令openssl rsa ... | openssl sha256
(全部作为一个 字符串)。在 Unix 上使用适当的 shell -- 这可能因您的系统而异,但 /bin/sh -c
是常见的。在 Windows 上使用 cmd.exe /c
.
仅供参考,如果您拥有或获得 BouncyCastle 库,它们可以读取相同的文件 openssl rsa
可以,并提取模数并对其进行格式化和散列,所有这些都直接在 Java 中而不使用 openssl
完全没有。但是你没有问这个,所以在 Stack 上它不是一个答案。
我的系统是 Windows 10 x64,所以您可能需要调整 openssl.exe 的路径。
开始解决路径我首先运行 OpenSSL-命令行:
openssl rsa -noout -modulus -in keyunencrypted.pem | openssl sha256
给出这个结果作为参考:
(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f
请注意,我使用的是“modulus”,而不是您的命令字符串中的“modules”。
开始 Java 体验,我了解到 opensll-command line 运行s 在 shell 中,但在 运行ning 时没有这样做
通过 Runtime.exec 的 OpenSSL。因此,有一种方法可以将完整的命令行拆分为两个单独的命令,通过 Output -> InputStream 组合在一起。在 Apache 的 common-io-library 的帮助下,有一个非常简单的解决方案可以做到这一点。您从 https://mvnrepository.com/artifact/commons-io/commons-io 获取库并
我使用 2.7 版进行测试。
以下示例取自 ,由用户@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("
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"};
//
// 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);
}
}
我有以下代码来执行 Openssl 命令并通过 Java Runtime
读取命令产生的输出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
注意:我已经在路径变量中设置了 bin 文件夹
我能够 运行 在 cmd 中执行命令并获得输出。我的要求是从命令 ouptut
中获取标准输入值非常感谢您的帮助!
首先,您显然在 PATH 环境变量的任何目录中都没有 openssl[.exe]
。要么更改您的 PATH 以包括包含 openssl 可执行文件的目录,要么更改您的代码以指定 openssl 可执行文件的完整路径名(因此它不需要使用 PATH)。如果在 Windows 上,请注意您可以在单个进程中或在注册表中全局更改 PATH;在后一种情况下,您需要 重新创建 使用 PATH 的任何进程,例如您的 'command' window、终端、shell、电源shell,或 IDE。欺骗 Java exec can't run program, error = 2 and CreateProcess error=2, The system cannot find the file specified .
其次,您拼写错误 -modulus
。
第三,将像 "|",etc
这样的重定向作为参数传递给 openssl
是行不通的。当您在 Unix 中向 shell 或 Windows 中的命令提示符键入 openssl rsa ... | openssl sha256
时,不会将 | openssl sha256
传递给第一个 openssl;相反,它 运行 是两个不同的进程,并将第一个进程的输出重定向到一个管道,并将第二个进程的输入重定向到该管道。 Runtime.exec()
不是命令处理器,不能执行此操作。您可以:
运行 仅
openssl rsa
部分,读取 Java 代码中的输出,并在 Java[ 中对该输出执行 SHA256 =24=]运行一个命令解释器并告诉它执行复合命令
openssl rsa ... | openssl sha256
(全部作为一个 字符串)。在 Unix 上使用适当的 shell -- 这可能因您的系统而异,但/bin/sh -c
是常见的。在 Windows 上使用cmd.exe /c
.
仅供参考,如果您拥有或获得 BouncyCastle 库,它们可以读取相同的文件 openssl rsa
可以,并提取模数并对其进行格式化和散列,所有这些都直接在 Java 中而不使用 openssl
完全没有。但是你没有问这个,所以在 Stack 上它不是一个答案。
我的系统是 Windows 10 x64,所以您可能需要调整 openssl.exe 的路径。
开始解决路径我首先运行 OpenSSL-命令行:
openssl rsa -noout -modulus -in keyunencrypted.pem | openssl sha256
给出这个结果作为参考:
(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f
请注意,我使用的是“modulus”,而不是您的命令字符串中的“modules”。
开始 Java 体验,我了解到 opensll-command line 运行s 在 shell 中,但在 运行ning 时没有这样做 通过 Runtime.exec 的 OpenSSL。因此,有一种方法可以将完整的命令行拆分为两个单独的命令,通过 Output -> InputStream 组合在一起。在 Apache 的 common-io-library 的帮助下,有一个非常简单的解决方案可以做到这一点。您从 https://mvnrepository.com/artifact/commons-io/commons-io 获取库并 我使用 2.7 版进行测试。
以下示例取自 ,由用户@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("
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"};
//
// 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);
}
}