java runtime.getruntime()从执行命令行程序获取输出

use*_*597 131 java runtime

我正在使用运行时从我的Java程序运行命令提示符命令.但是我不知道如何获得命令返回的输出.

这是我的代码:

Runtime rt = Runtime.getRuntime();

String[] commands = {"system.exe", "-send" , argument};

Process proc = rt.exec(commands);
Run Code Online (Sandbox Code Playgroud)

我尝试过,System.out.println(proc);但没有返回任何东西.该命令的执行应返回由分号分隔的两个数字,我怎样才能在变量中打印出来?

这是我现在使用的代码:

String[] commands = {"system.exe", "-get t"};

Process proc = rt.exec(commands);

InputStream stdIn = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdIn);
BufferedReader br = new BufferedReader(isr);

String line = null;
System.out.println("<OUTPUT>");

while ((line = br.readLine()) != null)
     System.out.println(line);

System.out.println("</OUTPUT>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
Run Code Online (Sandbox Code Playgroud)

但我没有得到任何东西作为我的输出,但当我自己运行该命令它工作正常.

Sen*_*hil 217

这是要走的路:

Runtime rt = Runtime.getRuntime();
String[] commands = {"system.exe", "-get t"};
Process proc = rt.exec(commands);

BufferedReader stdInput = new BufferedReader(new 
     InputStreamReader(proc.getInputStream()));

BufferedReader stdError = new BufferedReader(new 
     InputStreamReader(proc.getErrorStream()));

// Read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
    System.out.println(s);
}

// Read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
    System.out.println(s);
}
Run Code Online (Sandbox Code Playgroud)

更好地阅读更多细节的Javadoc 在这里.ProcessBuilder是一个很好的选择

  • @AlbertChen`pwd && ls`不只是执行单个文件,当你在shell中执行它时,它执行`/ bin/pwd`和`/ bin/ls`可执行文件.如果你想在java中做类似的东西,你需要做一些像`{"/ bin/bash"," - c","pwd && ls"}`的东西.你可能不再有这个问题,但其他人可能因此我认为我可能会回答它. (4认同)
  • 我认为读取两个流必须同时发生,因为如果像您的情况一样,stdStream的输出将填充缓冲区,您将无法读取错误流。 (2认同)
  • Li3ro部分正确。您正在收听的程序的stdout和stderr输出缓冲区有限。如果您不同时收听它们,则其中一个会在您阅读另一个时充满。然后,您正在收听的程序将阻止尝试写入已填充的缓冲区,而在另一端,您的程序将阻止尝试从永远不会返回“ EOF”的缓冲区进行读取。您必须同时从两个流中读取。 (2认同)
  • @AndreyTyukin你是对的。当前的所有答案都容易陷入僵局。我鼓励他们对他们投反对票,以使其他答案获得可见性。我发布了一个新答案供您审查:/sf/answers/4056482671/。希望我做对了...... (2认同)

735*_*sla 61

更快的方法是:

public static String execCmd(String cmd) throws java.io.IOException {
    java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}
Run Code Online (Sandbox Code Playgroud)

这基本上是这个的浓缩版本:

public static String execCmd(String cmd) throws java.io.IOException {
    Process proc = Runtime.getRuntime().exec(cmd);
    java.io.InputStream is = proc.getInputStream();
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    String val = "";
    if (s.hasNext()) {
        val = s.next();
    }
    else {
        val = "";
    }
    return val;
}
Run Code Online (Sandbox Code Playgroud)

我知道这个问题已经过时但是我发布了这个答案,因为我觉得这可能会更快.

  • "\ A"是钟形角色."^"是正则表达式中字符串的开头,"$"是正则表达式中字符串的结尾.这是一个你不希望看到的角色.根据Java文档,默认分隔符是空格,因此这样做可能会吐出命令的完整结果. (5认同)
  • 感谢您的好答案。为什么“ \\ A”是分隔符? (2认同)

And*_*son 11

除了使用ProcessBuilderSenthil建议之外,请务必阅读并实现Runtime.exec()不会的所有建议.


Gil*_*ili 11

在撰写本文时,所有其他包含代码的答案都可能导致死锁。

进程有一个有限的缓冲区stdoutstderr输出。如果您不同时听它们,当您尝试阅读另一个时,其中一个会填满。例如,您可能正在等待读取stdout而进程正在等待写入stderr. 您无法读取stdout缓冲区,因为它是空的,并且进程无法写入stderr缓冲区,因为它已满。你们每个人都在永远地等待对方。

这是一种在没有死锁风险的情况下读取进程输出的可能方法:

public final class Processes
{
    private static final String NEWLINE = System.getProperty("line.separator");

    /**
     * @param command the command to run
     * @return the output of the command
     * @throws IOException if an I/O error occurs
     */
    public static String run(String... command) throws IOException
    {
        ProcessBuilder pb = new ProcessBuilder(command).redirectErrorStream(true);
        Process process = pb.start();
        StringBuilder result = new StringBuilder(80);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())))
        {
            while (true)
            {
                String line = in.readLine();
                if (line == null)
                    break;
                result.append(line).append(NEWLINE);
            }
        }
        return result.toString();
    }

    /**
     * Prevent construction.
     */
    private Processes()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

关键是使用ProcessBuilder.redirectErrorStream(true)which 将重定向stderrstdout流中。这允许您读取单个流而无需在stdout和之间交替stderr。如果您想手动实现这一点,您将不得不在两个不同的线程中使用流以确保您永远不会阻塞。


nid*_*res 7

@Senthil和@Arend回答(/sf/answers/399780531/)提到了ProcessBuilder.以下是使用ProcessBuilder为命令指定环境变量和工作文件夹的示例:

    ProcessBuilder pb = new ProcessBuilder("ls", "-a", "-l");

    Map<String, String> env = pb.environment();
    // If you want clean environment, call env.clear() first
    //env.clear();
    env.put("VAR1", "myValue");
    env.remove("OTHERVAR");
    env.put("VAR2", env.get("VAR1") + "suffix");

    File workingFolder = new File("/home/user");
    pb.directory(workingFolder);

    Process proc = pb.start();

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

    BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

    // Read the output from the command:
    System.out.println("Here is the standard output of the command:\n");
    String s = null;
    while ((s = stdInput.readLine()) != null)
        System.out.println(s);

    // Read any errors from the attempted command:
    System.out.println("Here is the standard error of the command (if any):\n");
    while ((s = stdError.readLine()) != null)
        System.out.println(s);
Run Code Online (Sandbox Code Playgroud)


whi*_*win 7

如果已经在类路径上使用了Apache commons-io,则可以使用:

Process p = new ProcessBuilder("cat", "/etc/something").start();
String stderr = IOUtils.toString(p.getErrorStream(), Charset.defaultCharset());
String stdout = IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
Run Code Online (Sandbox Code Playgroud)


Jac*_*bec 6

我们也可以使用流来获取命令输出:

public static void main(String[] args) throws IOException {

        Runtime runtime = Runtime.getRuntime();
        String[] commands  = {"free", "-h"};
        Process process = runtime.exec(commands);

        BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        lineReader.lines().forEach(System.out::println);

        BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        errorReader.lines().forEach(System.out::println);
    }
Run Code Online (Sandbox Code Playgroud)