【问题标题】:How to execute shell command in Java?如何在 Java 中执行 shell 命令?
【发布时间】:2014-06-12 21:59:42
【问题描述】:

我在考虑是否可以发送一个 shell 来执行客户端-服务器 ipconfig。这可能吗?

这是我在本地的代码:

class Comando {
    public static void main(String args[]) {

        String s = null;

        try {

            // Determinar en qué SO estamos
            String so = System.getProperty("os.name");
            String comando;
            // Comando para Linux
            if (so.equals("Linux"))
                comando = "ifconfig";
            // Comando para Windows
            else
                comando = "ipconfig";

            // Ejcutamos el comando
            Process p = Runtime.getRuntime().exec(comando);

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

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

            // Leemos la salida del comando
            System.out.println("Ésta es la salida standard del comando:\n");
            while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }

            // Leemos los errores si los hubiera
            System.out
                    .println("Ésta es la salida standard de error del comando (si la hay):\n");
            while ((s = stdError.readLine()) != null) {
                System.out.println(s);
            }

            System.exit(0);
        } catch (IOException e) {
            System.out.println("Excepción: ");
            e.printStackTrace();
            System.exit(-1);
        }
    }
}

提前感谢您!

【问题讨论】:

    标签: java shell


    【解决方案1】:

    不是一个对 * 非常友好的问题,因为我不确定您是在询问 Shell 命令执行还是一般的 ipconfig。

    如果这里是第一种情况:是的,您可以使用Runtime.getRuntime.exec()。 相关答案(在 * 中):

    1. Executing shell commands from Java
    2. Want to invoke a linux shell command from Java

    除了那里提供的答案之外,这是我的示例,说明如何使用“host -t a”命令进行 DNS 查找。我通常建议通读您获得的列表并将它们附加到字符串中以用于记录目的。

    p = Runtime.getRuntime().exec("host -t a " + domain);
    p.waitFor();
    
    BufferedReader reader = 
      new BufferedReader(new InputStreamReader(p.getInputStream()));
    
    String line = "";           
    while ((line = reader.readLine())!= null) {
        sb.append(line + "\n");
    }
    

    herau建议的另一个解决方案是使用ProcessBuilder并从那里执行命令。为此,您需要使用 Java SE 7 以上版本。下面是一个示例,它使用修改后的工作目录和环境启动进程,并将标准输出和错误重定向到附加到日志文件中:

     ProcessBuilder pb =
       new ProcessBuilder("myCommand", "myArg1", "myArg2");
     Map<String, String> env = pb.environment();
     env.put("VAR1", "myValue");
     env.remove("OTHERVAR");
     env.put("VAR2", env.get("VAR1") + "suffix");
     pb.directory(new File("myDir"));
     File log = new File("log");
     pb.redirectErrorStream(true);
     pb.redirectOutput(Redirect.appendTo(log));
     Process p = pb.start();
     assert pb.redirectInput() == Redirect.PIPE;
     assert pb.redirectOutput().file() == log;
     assert p.getInputStream().read() == -1;
    

    如果您想了解更多有关 ProcessBuilder 的信息,请阅读文档:Oracle Documentation on Class ProcessBuilder

    【讨论】:

    • 但是我必须用这段代码为服务器创建另一个 .java 文件吗?
    • 嗯,是的,最佳实践:将相关的代码放在各自的块中。例如,创建一个 Util.java 并将其放在那里或更具体地说 ShellUtil.java 并创建一个通用函数,您可以在那里调用任何 shell 命令。
    • 在 JDK 5.0 之前,唯一的方法是使用 java.lang.Runtime 类的 exec() 方法。 JDK 5.0 之后,可以通过一个名为ProcessBuilder 的类在单独的进程中执行命令
    • 谢谢herau,我不知道ProcessBuilder,但你是对的。我也使用 Process Builder Option 更新了我的答案。
    • @devtreat 很高兴我的回答对你有帮助:)