Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Breaking out of FOR in batch

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)

like image 812
Niet the Dark Absol Avatar asked Mar 27 '12 15:03

Niet the Dark Absol


People also ask

How do I break out of a batch file?

Similar to Ctrl + C , pressing Ctrl + Pause/Break key aborts almost all batch files, commands, scripts, or other programs.

How do you exit a loop in CMD?

The only way to stop an infinitely loop in Windows Batch Script is by either pressing Ctrl + C or by closing the program.

What does for F mean in batch?

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.

How do you escape and in batch?

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.


2 Answers

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.

like image 113
dbenham Avatar answered Oct 06 '22 12:10

dbenham


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
like image 40
Erbert Avatar answered Oct 06 '22 13:10

Erbert