我目前的批次代码是:
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循环?
(或者,如果有更好的方法可以找到自由端口,请参阅我的somewhat-related question)
答案 0 :(得分:5)
你是对的,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地址和端口的专家,但我担心您的FIND逻辑可能不足以筛选已使用的端口。我认为之前寻找冒号并且在港口之后的空间将使其更可靠。另外,我怀疑你想看到使用过的端口的文本,所以我将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循环。在GOTO之后,只有FOR / L变体继续计数。
答案 1 :(得分: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