2012-03-27 26 views
6

Moja obecna linia kodu wsadowym jest:wyrwanie się z FOR w partii

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

Chodzi o to, aby znaleźć wolny port, który będzie używany do słuchania, w przedziale 8000-8100.

Obecnie mam port 8000 w użyciu, więc skrypt powinien iść do 8001.

Po pętli %tmp_freeport% jest równa 8001, jak powinno być, a jej wartość jest używana później poprawnie.

Problem polega na tym, że pętla działa niezależnie. netstat jest wywoływany w celu wyszukania wszystkich 101 portów w zakresie, co jest oczywiście nieefektywne i niechciane, ponieważ wyszukiwanie musi zakończyć się, zanim skrypt będzie mógł kontynuować.

Czy ktoś może mi powiedzieć, jak wyjść z partii pętli FOR?

(Alternatywnie, jeśli istnieje lepszy sposób na znalezienie wolnego portu, proszę zobaczyć moje somewhat-related question)

+1

Czy wypróbowałeś moją odpowiedź? zadziałało? –

Odpowiedz

5

Masz rację, że FOR/L pętli „zawsze” liczy się do końca. (No cóż, w rzeczywistości istnieją drastyczne metody kodowania, które mogą je złamać, ale nie ma potrzeby, aby tam jechać)

Jednak nawet jeśli pętla się liczy, klauzula DO zostanie pominięta po wykonaniu instrukcji GOTO FOUND. Możesz to udowodnić samodzielnie, wstawiając echo testing %%a& na początku istniejącej klauzuli DO. Przekonasz się, że nie ma żadnych dodatkowych testów, gdy znajdziesz swój wolny port.

Pętla FOR/L liczy się bardzo szybko (przynajmniej według standardów wsadowych), więc nie przejmowałbym się dodatkowym liczeniem. Teraz, jeśli liczyłeś od 1 do 1 miliona, wtedy może martwić się o. Na 10 milionów jestem zdecydowanie zaniepokojony.

Mogę nieco uprościć istniejącą logikę. Możesz łączyć 2 instrukcje FIND w pojedynczy FINDSTR za pomocą wyrażenia regularnego.

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

Nie jestem ekspertem dotyczące adresów IP i portów, ale obawiam się, że logika ZNAJDŹ może być niewystarczająca do badań przesiewowych stosowanych portów. Myślę, że szukanie dwukropka przedtem i spacja po porcie sprawi, że będzie on bardziej niezawodny. Ponadto wątpię, że chcesz zobaczyć tekst używanych portów, więc przekierowałem wyjście FINDSTR do nul.

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

Uwaga: GOTO: Wytwórnia natychmiast rozwiązać wszystkie inne formy pętli FOR. Tylko wariant FOR/L nadal liczy się po GOTO.

+0

Dobra, więc nawet jeśli polecenia są wyświetlane, gdy ECHO jest włączone, nie są one faktycznie wykonywane? Miło wiedzieć, i wyjaśnia, dlaczego wynik jest nadal "8001". –

4

Możesz zamiast tego użyć IF i GOTO. Coś jak:

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