【问题标题】:Running Windows Command in Java Using Runtime.getRuntime().exec(String[])使用 Runtime.getRuntime().exec(String[]) 在 Java 中运行 Windows 命令
【发布时间】:2014-09-25 17:07:51
【问题描述】:

我在从 java 运行这个令人困惑的 windows 命令时遇到了一点问题,我找不到任何与我试图做的代码类似的东西。

基本上,windows 命令会杀死任何与具有 CLOSE_WAIT 状态并与指定的特定 ip:port 相关的套接字相关的 PID。我的问题是我很难使用 Runtime.getRuntime().exec() 让它运行。

String[] command = {"cmd /c for /f \"tokens=5\" %a in ('netstat -noa -p tcp ^| find /i \"CLOSE_WAIT\" ^| find /i \""+ip+":443\" ') do if not \"%a\"==\"0\" echo taskkill /pid %a"};     
Process runCommand = Runtime.getRuntime().exec(command);
runCommand.waitFor(); 

执行此操作时,我目前收到错误消息:

class java.io.IOException 消息:无法运行程序“C:/ cmd /c for /f "tokens=5" %a in ('netstat -noa -p tcp ^| 找到 /i "CLOSE_WAIT" ^| find /i "ip:443" ') 如果不是 "%a"=="0" echo taskkill /pid %a" 则执行: CreateProcess error=2, 系统找不到指定的文件

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 先尝试在cmd中执行该命令并检查该命令是否为有效命令!
  • 您是否尝试过使用 Windows 命令创建 .bat 文件并通过 runtime.exec() 运行 .bat?
  • 嗯,我实际上刚刚做了,我得到了一个 '|在这个时候出乎意料'错误消息我不想通过 bat 文件运行它,因为这会涉及到我的代码库中添加一些混乱,我需要传递我想要关闭套接字的系统的 ip。我尽量保留尽可能少的文件。

标签: java windows command-line


【解决方案1】:

通过传递 String[] 数组而不是单个 String,您是在告诉系统运行单个 .exe 文件,该文件的名称包含大约 144 个字符,其中前 13 个字符是 cmd /c for /f。显然没有同名的 .exe 文件。

您可以尝试的一件事是将单个字符串传递给exec(String) 方法,而不是传递字符串数组。这可能有效,也可能无效,因为 Java 会将您的字符串拆分为以空格分隔的单词,然后 Windows 会试探性地尝试找出您想要的内容。

另一种可行的方法是包含 3 个元素的字符串数组:

String[] command = { "cmd", "/c", "for /f \"tokens=5\" %a in ('netstat -noa -p tcp ^| find /i \"CLOSE_WAIT\" ^| find /i \""+ip+":443\" ') do if not \"%a\"==\"0\" echo taskkill /pid %a" };

在我看来,最好的办法是不要依赖 cmd.exe 来解析命令行参数。我怀疑 Java 在处理文本方面至少同样有效:

Collection<String> pids = new ArrayList<>();

ProcessBuilder p = new ProcessBuilder("netstat.exe", "-noa", "-p", "tcp");
p.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process netstat = p.start();

try (BufferedReader output =
    new BufferedReader(new InputStreamReader(netstat.getOutputStream()))) {

    String line;
    while ((line = output.readLine()) != null) {

        if (line.toUpperCase().contains("CLOSE_WAIT") &&
            line.contains(ip + ":443")) {

            String[] tokens = line.split("\\s+");
            String pid = tokens[4];
            if (!pid.equals("0")) {
                pids.add(pid);
            }
        }
    }
}

if (netstat.waitFor() != 0) {
    throw new IOException("netstat command failed");
}

p.inheritIO();
for (String pid : pids) {
    Process taskkill = p.command("taskkill.exe", "/pid", pid).start();
    taskkill.waitFor();
}

如果您使用的是 Java 8,您还可以使用 Streams 编写更类似于管道命令的代码:

ProcessBuilder p = new ProcessBuilder("netstat.exe", "-noa", "-p", "tcp");
p.inheritIO().redirectOutput(ProcessBuilder.Redirect.PIPE);
Process netstat = p.start();

try (BufferedReader output =
    new BufferedReader(new InputStreamReader(netstat.getOutputStream()))) {

    final ProcessBuilder taskkill = new ProcessBuilder().inheritIO();

    output.lines()
        .filter(line -> line.toUpperCase().contains("CLOSE_WAIT") &&
            line.contains(ip + ":443"))
        .map(line -> line.split("\\s+")[4])
        .filter(pid -> !pid.equals("0"))
        .forEach(pid ->
            taskkill.command("taskkill.exe", "/pid", pid).start());
}

if (netstat.waitFor() != 0) {
    throw new IOException("netstat command failed");
}

【讨论】:

    猜你喜欢
    • 2017-01-03
    • 2019-09-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多