2012-03-27 14 views
6

Mi actual línea de código del lote es:Salir de DE en el lote

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

La idea es encontrar un puerto libre que será utilizado para la escucha, dentro de la gama de 8000-8100.

Actualmente, tengo el puerto 8000 en uso, por lo que la secuencia de comandos debería ir a 8001.

después del bucle, %tmp_freeport% es igual a 8001, como debe ser, y su valor se utiliza posteriormente correctamente.

El problema es que el ciclo sigue funcionando independientemente. Se llama a netstat para buscar los 101 puertos del rango, lo que obviamente es ineficiente y no deseado, porque la búsqueda debe completarse antes de que el script pueda continuar.

¿Alguien me puede decir cómo salir de un bucle FOR batch?

(Alternativamente, si hay una mejor manera de encontrar un puerto libre, por favor ver mi somewhat-related question)

+1

¿Ha probado mi respuesta? ¿funcionó? –

Respuesta

5

Tiene razón en que un/L de bucle para "Siempre" cuenta hasta su finalización. (Bueno, en realidad hay algunos métodos de codificación drásticos que pueden romperlo, pero no es necesario ir allí)

Sin embargo, aunque el ciclo cuenta hasta su finalización, la cláusula DO se salta una vez que se ha ejecutado la instrucción GOTO FOUND. Puede probar esto a usted mismo insertando echo testing %%a& en el frente de su cláusula DO existente. Verá que no se realizan pruebas adicionales una vez que haya encontrado su puerto libre.

El ciclo FOR/L cuenta muy rápido (al menos por lotes), así que no me preocuparía el recuento adicional. Ahora bien, si estuviera contando de 1 a 1 millón, entonces yo podría preocuparme. En 10 millones definitivamente estoy preocupado.

Puedo simplificar un poco tu lógica existente. Puede combinar las 2 instrucciones FIND en un solo FINDSTR usando una expresión regular.

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

No soy experto en relación con las direcciones IP y los puertos, pero me preocupa que la lógica de FIND puede ser inadecuado para la detección de puertos utilizados. Creo que buscar un colon antes y un espacio después del puerto lo hará más confiable. Además, dudo que quiera ver el texto de los puertos usados, así que redirigí la salida FINDSTR a nul.

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

Nota: GOTO: Etiqueta terminará inmediatamente todas las otras formas de un bucle FOR. Solo la variante FOR/L continúa contando después de un GOTO.

+0

Bien, entonces, aunque los comandos se enumeran cuando ECHO está activado, ¿en realidad no se están ejecutando? Es bueno saberlo y explica por qué el resultado sigue siendo '8001'. –

4

En su lugar, puede usar IF y GOTO. Algo como:

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