如何 运行 在 Java 中的终端上 运行 命令
How to run commands you can run on terminal in Java
伙计们,我想执行一个命令,您可以在我的 Java 程序中的 cmd 上执行该命令。在做了一些研究之后,我想我找到了一种方法来做到这一点。但是,我的代码不起作用。
我的密码是
import java.io.*;
public class CmdTest {
public static void main(String[] args) throws Exception {
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File("./test-java/"));
Process p = builder.start();
}
}
程序执行但没有输出。我尝试使用其他命令,如 "ls -a",但仍然没有输出。
有人可以帮我调试这个或建议一个更好的方法吗?谢谢
编辑 1:我正在 Mac 上执行此操作。如果这是调试所必需的
编辑 2:常用的 ls 和其他命令正在使用你们提供的解决方案。但是我想在 Java 程序中使用 ag (the_silver_searcher) 命令。当我尝试这样做时,出现以下错误 -
Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory
虽然有ProcessBuilder
,但我一直用Runtime.getRuntime().exec("cmd");
它returns一个Process可以得到
的输入输出流
即使您继续使用 ProcessBuilder
,您仍然应该可以访问 Process.get<Input/Output/Error>Stream()
您需要通过打开进程的输入流来读取进程的输出:
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())) {
System.out.println(reader.readLine()); // process the output stream somehow
}
此外,您可能会读取错误流 (p.getErrorStream()
),我经常在单独的流中完成此操作,在 Java 8 中,您可以在 ProcessBuilder
自动将错误流添加到输入流。当然,您无法再区分输入来自哪个流,但它使阅读更容易。如果您不读取输入或错误流并且进程的缓冲区已满,则进程往往会暂停,直到缓冲区中再次有足够的空间。
您还可以添加
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
在将输出重定向到控制台的启动方法之前。
//"ls" command runs under the "sh" on linux(cmd.exe on windows), so first arg is "sh"
//second arg "-c" tells "sh" which exact command should be executed
//"ls" is actual command
//"startTimes" as I understand is a file or directory, it is arg for "ls" command
//"conf.js" is second arg for "ls" command
new ProcessBuilder("sh", "-c", "ls", "startTimes", "conf.js")
//set working dir for "sh" process"
.directory(new File("./test-java/"))
//output will be written to "pro.txt" in working dir of "sh" process
.redirectOutput(new File("./test-java/pro.txt"))
.start();
现有答案为您提供了有关如何在代码中解决问题的信息,但没有给出您的代码无法正常工作的原因。
当您在 shell 上执行程序时,shell 在执行程序之前会进行大量处理。你的命令行
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
假设命令 ag
是 运行,带有 单个 参数 startTimes conf.js >> pro.txt
- 很可能不是您想要的。让我们更进一步:如果你写
String[] command = {"ag","startTimes", "conf.js", ">>", "pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
?
这将假定 ag
命令知道 >>
参数以重定向其输出 - 这就是 shell 发挥作用的地方: >>
运算符是 到 shell 的指令,告诉 它 如何处理进程标准输出的输出。进程 ag
,当由 shell 启动时,从来不知道这种重定向,并且根本不知道 >>
和目标文件名。
有了这些信息,只需使用任何其他答案中的代码示例即可。我不会为了适当的归属而将它们复制到我的。
伙计们,我想执行一个命令,您可以在我的 Java 程序中的 cmd 上执行该命令。在做了一些研究之后,我想我找到了一种方法来做到这一点。但是,我的代码不起作用。
我的密码是
import java.io.*;
public class CmdTest {
public static void main(String[] args) throws Exception {
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
builder.directory(new File("./test-java/"));
Process p = builder.start();
}
}
程序执行但没有输出。我尝试使用其他命令,如 "ls -a",但仍然没有输出。
有人可以帮我调试这个或建议一个更好的方法吗?谢谢
编辑 1:我正在 Mac 上执行此操作。如果这是调试所必需的
编辑 2:常用的 ls 和其他命令正在使用你们提供的解决方案。但是我想在 Java 程序中使用 ag (the_silver_searcher) 命令。当我尝试这样做时,出现以下错误 -
Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory
虽然有ProcessBuilder
,但我一直用Runtime.getRuntime().exec("cmd");
它returns一个Process可以得到
的输入输出流即使您继续使用 ProcessBuilder
,您仍然应该可以访问 Process.get<Input/Output/Error>Stream()
您需要通过打开进程的输入流来读取进程的输出:
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())) {
System.out.println(reader.readLine()); // process the output stream somehow
}
此外,您可能会读取错误流 (p.getErrorStream()
),我经常在单独的流中完成此操作,在 Java 8 中,您可以在 ProcessBuilder
自动将错误流添加到输入流。当然,您无法再区分输入来自哪个流,但它使阅读更容易。如果您不读取输入或错误流并且进程的缓冲区已满,则进程往往会暂停,直到缓冲区中再次有足够的空间。
您还可以添加
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
在将输出重定向到控制台的启动方法之前。
//"ls" command runs under the "sh" on linux(cmd.exe on windows), so first arg is "sh"
//second arg "-c" tells "sh" which exact command should be executed
//"ls" is actual command
//"startTimes" as I understand is a file or directory, it is arg for "ls" command
//"conf.js" is second arg for "ls" command
new ProcessBuilder("sh", "-c", "ls", "startTimes", "conf.js")
//set working dir for "sh" process"
.directory(new File("./test-java/"))
//output will be written to "pro.txt" in working dir of "sh" process
.redirectOutput(new File("./test-java/pro.txt"))
.start();
现有答案为您提供了有关如何在代码中解决问题的信息,但没有给出您的代码无法正常工作的原因。
当您在 shell 上执行程序时,shell 在执行程序之前会进行大量处理。你的命令行
String[] command = {"ag","startTimes conf.js >> pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
假设命令 ag
是 运行,带有 单个 参数 startTimes conf.js >> pro.txt
- 很可能不是您想要的。让我们更进一步:如果你写
String[] command = {"ag","startTimes", "conf.js", ">>", "pro.txt"};
ProcessBuilder builder = new ProcessBuilder(command);
?
这将假定 ag
命令知道 >>
参数以重定向其输出 - 这就是 shell 发挥作用的地方: >>
运算符是 到 shell 的指令,告诉 它 如何处理进程标准输出的输出。进程 ag
,当由 shell 启动时,从来不知道这种重定向,并且根本不知道 >>
和目标文件名。
有了这些信息,只需使用任何其他答案中的代码示例即可。我不会为了适当的归属而将它们复制到我的。