2014-09-25 139 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"); 
} 
相關問題