【问题标题】:How do I call this command via Java's Runtime.getRuntime().exec method? [duplicate]如何通过 Java 的 Runtime.getRuntime().exec 方法调用此命令? [复制]
【发布时间】:2015-05-19 00:38:04
【问题描述】:

以下命令在我的 Linux 终端中正确运行:

java -Djava.library.path=/home/john/native_so_libraries/linux-64 -cp '/home/john/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohn/Desktop/Dropbox/Libjitsi_linux_64/*' Main "send"

此命令指定本地 .so 库的文件夹(通过 Djava.library.path=/...)、名为“SendReceive.jar”的应用程序 JAR 文件、JAR 库的文件夹(通过 -cp 类路径选项),还有一个包含要运行的主要方法的主类,一个名为“Main”的类。它有一个用引号括起来的命令行参数,即“send”参数。此命令有效并从终端运行 Java 进程,但我无法弄清楚如何让它与来自另一个进程的 Runtime.getRuntime().exec 一起工作。

请注意,我正在尽最大努力遵循本教程中提供的说明:http://www.javaworld.com/article/2071275/core-java/when-runtime-exec---won-t.html?page=2 - 这意味着我正在使用线程来使用进程中的标准输入和标准错误流。尽管如此,当我将该终端命令变成这样的字符串时,该过程仍不会开始:

Process process = Runtime.getRuntime().exec("java -Djava.library.path=/home/john/native_so_libraries/linux-64 -cp '/home/john/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohn/Desktop/Dropbox/Libjitsi_linux_64/*' Main \"send\"");

如何让这个命令通过 Runtime.getRuntime().exec 运行?

【问题讨论】:

    标签: java linux process runtime.exec


    【解决方案1】:

    简短的回答是不要。请改用ProcessBuilder。它允许您将每个命令行参数分成它自己的String,这将作为一个单独的“参数”出现在进程中。这对于处理其中包含空格的路径非常有用,例如...

    ProcessBuilder pb = new ProcessBuilder(
                    "java", 
                    "-Djava.library.path=/home/johnmichaelreed/Desktop/Dropbox/Libjitsi_linux_64/lib/native/linux-64", 
                    "-cp", 
                    "/home/johnmichaelreed/NetBeansProjects/SendReceive/dist/SendReceive.jar:/home/j‌​ohnmichaelreed/Desktop/Dropbox/Libjitsi_linux_64", 
                    "Main", 
                    "\"send\"");
    
    pb.redirectErrorStream(true);
    try {
        Process p = pb.start();
        try (InputStream is = p.getInputStream()) {
            int in = -1;
            while ((in = is.read()) != -1) {
                System.out.print((char)in);
            }
        }
        int exitCode = p.exitValue();
    
        System.out.println("Process exited with " + exitCode);
    } catch (IOException ex) {
        ex.printStackTrace();
    }
    

    它还允许您将 stderr 重定向到 stdout,从而使其更易于阅读。

    您还应该阅读标准输出并检查退出值以获得更好的诊断

    【讨论】:

      【解决方案2】:

      您需要做的第一件事是执行glob(在您的类路径中由* 表示)。您还可以使用ProcessBuilder - 用于创建操作系统进程。 而且,List<String> 或命令和StringBuilder 用于执行 glob。类似的,

      public static void main(String[] args) {
          String home = System.getProperty("user.home");
          System.out.println(home);
          List<String> command = new ArrayList<>();
          command.add("java");
          command.add("-Djava.library.path=" + home
                  + "/native_so_libraries/linux-64");
          StringBuilder cp = new StringBuilder();
          cp.append(home + "/NetBeansProjects/SendReceive/dist/SendReceive.jar");
          try {
              File dir = new File(home + "/Desktop/Dropbox/"
                      + "Libjitsi_linux_64/");
              for (File f : dir.listFiles()) {
                  if (f.isFile()) {
                      cp.append(":").append(f.getCanonicalPath());
                  }
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
      
          command.add("-cp");
          command.add(cp); // <-- shouldn't need literal
                          // single quotes.
          command.add("Main");
          command.add("send"); // <-- shouldn't need literal double quotes.
          ProcessBuilder pb = new ProcessBuilder(command);
          pb.inheritIO();
          try {
              Process p = pb.start();
              System.exit(p.waitFor());
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
      

      【讨论】:

      • 不应该 command.add("-cp " + cp.toString()) 将参数分开,否则它将作为单个参数呈现给进程,当它期望两个时......
      • @MadProgrammer 是的。接得好。谢谢。
      猜你喜欢
      • 1970-01-01
      • 2017-01-03
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 2014-03-21
      • 1970-01-01
      • 2013-01-21
      相关资源
      最近更新 更多