Вырваться из FOR в партии - PullRequest
6 голосов
/ 27 марта 2012

Моя текущая строка кода пакета:

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?

(В качестве альтернативы, если есть лучший способ найти свободный порт, см. Мой несколько связанный вопрос )

Ответы [ 2 ]

5 голосов
/ 27 марта 2012

Вы правы, что цикл FOR / L "всегда" считается завершенным.(Ну, на самом деле есть некоторые радикальные методы кодирования, которые могут его сломать, но нет необходимости идти туда)

Однако, хотя цикл считается до конца, предложение DO пропускается после того, как оператор GOTO FOUND былказнены.Вы можете доказать это себе, вставив echo testing %%a& в начале существующего предложения DO.Как только вы найдете свободный порт, вы увидите, что дополнительное тестирование не проводится.

Цикл FOR / L считает очень быстро (по крайней мере, по пакетным стандартам), поэтому я не буду беспокоиться о дополнительном подсчете.Если бы вы считали от 1 до 1 миллиона, то я бы мог бы волноваться.На 10 миллионов я определенно обеспокоен.

Я могу немного упростить вашу существующую логику.Вы можете объединить 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: Метканемедленно прекратит все другие формы цикла FOR.Только вариант FOR / L продолжает считать после GOTO.

4 голосов
/ 28 марта 2012

Вы можете просто использовать 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
...