How to kill a CLOSE_WAIT state process preferably by port 80 in WINDOWS with batch script

Christopher Glenn Schlägel picture Christopher Glenn Schlägel · Sep 30, 2014 · Viewed 21.9k times · Source

Summary: Rogue java processes from lingering stopped services preventing service from returning.

Stopping a java service doesn't kill the java process on occasion, it locks it in a CLOSE_WAIT status endlessly, so port 80 is still being used on the IP when the service attempts to return, thus the service fails to start

Doing a netstat -ano returns the PID of the IP/PORT combination, then I can kill it manually. I'd like to prevent myself from having to do this. I'd like to add to our service restart script a section that will kill any port 80 process in the CLOSE_WAIT status.

I can do this in Linux easily enough:

$ netstat -anp |\
grep ':80 ' |\
grep CLOSE_WAIT |\
awk '{print $7}' |\
cut -d \/ -f1 |\
grep -oE "[[:digit:]]{1,}" |\
xargs kill

But my windows batch scripting skills are pretty sub-par.

Can anyone assist in a windows equivalent to get this done?

Answer

Victor picture Victor · Sep 30, 2014

Here you have something you could use (run it as a .bat):

echo off
netstat -ano | find "127.0.0.1:80" | find "CLOSE_WAIT" > out.txt

FOR /F "tokens=5 delims= " %%I IN (out.txt) DO (
    TASKKILL %%I
)

del out.txt

It can be done as a single command (without having the .bat file) but I think this is more readable.

UPDATE

An improvement of the script shown above, you can avoid using the temporary file by enclosing the piped command in the for loop using single quotes and carets (^) before the pipes simbol (|):

FOR /F "tokens=5 delims= " %%I IN (
    'netstat -ano ^| find "127.0.0.1:80" ^| find "CLOSE_WAIT"'
) DO (
    taskkill /PID %%I
)

The help of the for /F commands explains it better:

Finally, you can use the FOR /F command to parse the output of a command. You do this by making the file-set between the parenthesis a back quoted string. It will be treated as a command line, which is passed to a child CMD.EXE and the output is captured into memory and parsed as if it was a file. So the following example: FOR /F "usebackq delims==" %i IN (set) DO @echo %i

Credits to this answer for the caret solution