My current line of batch code is:
for /L %%a in (8000,1,8100) do netstat /a /n | find "%%a" | find "LISTENING" || set tmp_freeport=%%a && goto found
The idea is to find a free port that will be used for listening, within the range of 8000-8100.
Currently, I have port 8000 in use, so the script should go to 8001.
After the loop, %tmp_freeport%
is equal to 8001, as it should be, and its value is used later correctly.
The problem is that the loop keeps running regardless. netstat
is called to search for all 101 ports in the range, which is obviously inefficent and unwanted, because the search must complete before the script can continue.
Can anyone tell me how to break out of a batch FOR loop?
(Alternatively, if there's a better way of finding a free port, please see my somewhat-related question)
Similar to Ctrl + C , pressing Ctrl + Pause/Break key aborts almost all batch files, commands, scripts, or other programs.
The only way to stop an infinitely loop in Windows Batch Script is by either pressing Ctrl + C or by closing the program.
FOR /F processing of a command consists of reading the output from the command one line at a time and then breaking the line up into individual items of data or 'tokens'. The DO command is then executed with the parameter(s) set to the token(s) found.
When working at the command line or with batch files, you must take one of two actions when you use strings that contain an ampersand. Either you must escape the ampersand by using the caret (^) symbol, or you must enclose the string inside quotation marks.
You are correct that a FOR /L loop "always" counts to completion. (Well, actually there are some drastic coding methods that can break it, but no need to go there)
However, even though the loop counts to completion, the DO clause is skipped once the GOTO FOUND statement has been executed. You can prove this to yourself by inserting echo testing %%a&
in the front of your existing DO clause. You will see that no additional testing takes place once you have found your free port.
The FOR /L loop counts very fast (at least by batch standards), so I wouldn't worry about the extra counting. Now if your were counting 1 through 1 million, then I might worry. At 10 million I am definitely concerned.
I can simplify your existing logic a bit. You can combine the 2 FIND statements into a single FINDSTR using a regular expression.
for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:"%%a.*LISTENING" || set tmp_freeport=%%a && goto found
I am no expert concerning IP addresses and ports, but I am concerned that your FIND logic may be inadequate to screen for used ports. I think looking for a colon before and a space after the port will make it more reliable. Also, I doubt you want to see the text of the used ports, so I redirected the FINDSTR output to nul.
for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:":%%a .*LISTENING" >nul || set tmp_freeport=%%a && goto found
Note: GOTO :Label will immediately terminate all other forms of a FOR loop. Only the FOR /L variant continues to count after a GOTO.
You could just use IF and GOTO instead. Something like:
SET /A a=8000
:loop
(Search and set variable here, use %a% instead of %%a, then GOTO found if found.)
SET /A a=a+1
IF %a% LEQ 8100 GOTO loop
:found
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With