1

I'm having a little bit of trouble running this confusing windows command from java and I can't find anything that is similar to what I'm trying to do to base my code against.

Basically the windows command kills any PIDs relating to sockets with a CLOSE_WAIT status and related to the specific ip:port specified. My issue is I'm having a hard time getting it to run using 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(); 

While doing this I am current getting the error message:

class java.io.IOException Message: Cannot run program "C:/ 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": CreateProcess error=2, The system cannot find the file specified

Any help would be much appreciated. Thanks!

3
  • Try to execute that command in cmd first and check whether that command is a valid command or not! Commented Sep 25, 2014 at 17:10
  • Have you tried creating a .bat file with your windows command and running the .bat via runtime.exec()? Commented Sep 25, 2014 at 17:10
  • Hmm I actually just did and I get a '| was unexpected at this time' error message I do not want to run it via a bat file because that would involve adding some clutter to my codebase and I need to pass the ip of the system I want to close the socket with. I try and keep as little amount of files as possible. Commented Sep 25, 2014 at 17:15

1 Answer 1

2

By passing a String[] array rather than a single String, you are telling the system to run a single .exe file whose name contains about 144 characters, the first thirteen of which are cmd /c for /f. Obviously there is no .exe file with that name.

One thing you can try is passing that single String to the exec(String) method instead of passing an array of Strings. This may or may not work, as Java will split your string into whitespace-delimited words, and then Windows will heuristically try to figure out what you want.

Another approach that may work is a String array containing 3 elements:

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" };

The best thing to do, in my opinion, is not to rely on cmd.exe for parsing command line arguments. I suspect Java is at least as efficient at processing text:

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

If you're using Java 8, you can also use Streams to write code that more closely resembles piped commands:

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");
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.