2014-09-25 135 views
0

我在运行这个令人困惑的Windows命令从java中遇到了一点麻烦,我找不到任何与我相似的东西试图做我的代码反对。在Java中运行Windows命令使用Runtime.getRuntime()。exec(String [])

基本上,windows命令会杀死任何与具有CLOSE_WAIT状态并与指定的特定ip:端口相关的套接字的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(); 

虽然这样做我当前得到的错误消息:

类java.io.IOException的消息:不能运行程序 “C:用于 /F/CMD/C” 令牌= 5 “%a in('netstat -noa -p tcp^| find/i”CLOSE_WAIT“^ | find/i”ip:443“')如果不是”%a“==”0“echo taskkill/pid% a“: CreateProcess error = 2,系统找不到指定的文件

任何帮助w应该非常感谢。谢谢!

+0

尝试首先在'cmd'中执行该命令并检查该命令是否是有效的命令! – 2014-09-25 17:10:40

+0

您是否尝试使用Windows命令创建.bat文件并通过runtime.exec()运行.bat? – MarsAtomic 2014-09-25 17:10:48

+0

嗯我其实只是做了,我得到了一个'|这是意外的'错误消息 我不想通过bat文件运行它,因为这会涉及到添加一些混乱到我的代码库,我需要通过系统的IP我想关闭套接字。我尽量保留尽可能少的文件。 – user3459799 2014-09-25 17:15:19

回答

1

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

您可以尝试的一件事是将该单个字符串传递给exec(String)方法,而不是传递字符串数组。这可能会也可能不行,因为Java会将您的字符串分割成空白分隔的单词,然后Windows会启发式地试图找出您想要的内容。

可能工作的另一种方法是包含三个元素的String数组:

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中,您还可以使用流编写代码,从而更接近管道命令:

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().waitFor()); 
} 

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