跳出批处理中的FOR循环

8

我当前的批处理代码如下:

for /L %%a in (8000,1,8100) do netstat /a /n | find "%%a" | find "LISTENING" || set tmp_freeport=%%a && goto found

找到一个空闲端口用于监听,端口号范围在8000-8100之间。
目前,端口8000正在使用,所以脚本应该使用8001。
循环结束后,%tmp_freeport% 的值应该是8001,并且它的值会被正确地使用。
问题在于无论如何循环都会一直运行。调用netstat搜索范围内的所有101个端口,这显然是低效和不必要的,因为搜索必须在脚本继续之前完成。
有人能告诉我如何退出批处理FOR循环吗?
(或者,如果有更好的方法找到空闲端口,请参见我的相关问题

1
你试过我的答案了吗?它有效吗? - Radu Gheorghiu
2个回答

6
你是正确的,FOR /L循环“总是”计数至完成。(好吧,实际上有一些激进的编码方法可以打破它,但没必要去那里)
然而,即使循环计数到完成,一旦执行了GOTO FOUND语句,DO子句就会被跳过。你可以通过在现有DO子句前插入echo testing %%a& 来证明这一点。你会发现一旦找到空闲端口后,就不会再进行其他测试了。
FOR /L循环计数得非常快(至少按批处理标准来说),所以我不用担心额外的计算。如果你要计数从1到100万,那么我可能会有点担心。而1000万时我肯定会担心。
我可以稍微简化一下您现有的逻辑。您可以将2个FIND语句合并为单个使用正则表达式的FINDSTR。
for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:"%%a.*LISTENING" || set tmp_freeport=%%a && goto found

我不是一个关于IP地址和端口的专家,但我担心你的查找逻辑可能无法筛选出已使用的端口。我认为在端口前寻找冒号并在其后寻找一个空格会使它更加可靠。此外,我怀疑您不想看到已使用端口的文本,所以我将FINDSTR输出重定向到nul。

for /L %%a in (8000,1,8100) do netstat /a /n | findstr /rc:":%%a .*LISTENING" >nul || set tmp_freeport=%%a && goto found

注意: GOTO :Label会立即终止FOR循环的所有其他形式。只有FOR /L变体在GOTO之后继续计数。


好的,所以即使在 ECHO 打开时列出了命令,它们实际上并没有被执行?这很好知道,并解释了为什么结果仍然是“8001”。 - Niet the Dark Absol

4
你可以使用 IF 和 GOTO 来代替。类似这样:
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接