Jak najłatwiej znaleźć nieużywany port lokalny?
Obecnie używam czegoś podobnego do tego:
port=$RANDOM
quit=0
while [ "$quit" -ne 1 ]; do
netstat -a | grep $port >> /dev/null
if [ $? -gt 0 ]; then
quit=1
else
port=`expr $port + 1`
fi
done
Czuje się strasznie rondo, więc zastanawiam się, czy istnieje prostsza ścieżka, na przykład wbudowana, za którą tęskniłem.
shell
networking
shell-script
netstat
mybuddymichael
źródło
źródło
-n
do netstat i bardziej selektywnego grep). Można to zrobić, próbując otworzyć port w dowolnym trybie, którego potrzebujesz, i wypróbować inny, jeśli nie jest dostępny.ssh -D
jako serwer SOCKS.Odpowiedzi:
Jeśli aplikacja obsługuje tę funkcję, możesz spróbować przekazać port 0 do aplikacji. Jeśli aplikacja przekaże to do jądra, port zostanie przydzielony dynamicznie w czasie żądania i gwarantuje, że nie będzie używany (przydział nie powiedzie się, jeśli wszystkie porty są już w użyciu).
W przeciwnym razie możesz to zrobić ręcznie. Skrypt w twojej odpowiedzi ma warunek wyścigu, jedynym sposobem na uniknięcie go jest atomowe sprawdzenie, czy jest otwarte, próbując je otworzyć. Jeśli port jest w użyciu, program powinien zakończyć pracę z niepowodzeniem otwarcia portu.
Powiedzmy na przykład, że próbujesz słuchać za pomocą GNU netcat.
źródło
$port
w rzeczywistym programie jak wwhile ...; done; program --port $port
.Moim rozwiązaniem jest powiązanie z portem 0, który prosi jądro o przydzielenie portu z jego ip_local_port_range. Następnie zamknij gniazdo i użyj tego numeru portu w konfiguracji.
Działa to, ponieważ jądro wydaje się nie używać numerów portów, dopóki nie będzie to absolutnie konieczne. Kolejne powiązania z portem 0 przypiszą inny numer portu. Kod Python:
Daje to tylko numer portu, np.
60123
.Uruchom ten program 10 000 razy (powinieneś je uruchomić jednocześnie), a otrzymasz 10 000 różnych numerów portów. Dlatego myślę, że korzystanie z portów jest dość bezpieczne.
źródło
python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
{ 1: 7006, 2: 1249, 3: 151, 4: 8, 5: 1, 6: 1}
ruby -e 'puts Addrinfo.tcp("", 0).bind { |s| s.local_address.ip_port }'
Jednowarstwowa
Stworzyłem ładny jednowarstwowy, który szybko służy temu celowi, pozwalając złapać dowolną liczbę portów w dowolnym zakresie (tutaj jest podzielony na 4 linie dla czytelności):
Linia po linii
comm
to narzędzie, które porównuje linie w dwóch plikach, które muszą pojawiać się posortowane alfabetycznie. Wyprowadza trzy kolumny: linie, które pojawiają się tylko w pierwszym pliku, linie, które pojawiają się tylko w drugim, i linie wspólne. Określając-23
, pomijamy te ostatnie kolumny i zachowujemy tylko pierwszą. Możemy tego użyć, aby uzyskać różnicę dwóch zestawów, wyrażoną jako ciąg wierszy tekstu. Dowiedziałem sięcomm
tutaj .Pierwszy plik to zakres portów, które możemy wybrać.
seq
tworzy posortowaną sekwencję liczb od$FROM
do$TO
. Wynik jest sortowany alfabetycznie (zamiast numerycznie) i przesyłany docomm
pierwszego pliku za pomocą podstawienia procesu .Drugi plik to posortowana lista portów, którą uzyskujemy przez wywołanie
ss
polecenia (w-t
znaczeniu portów TCP,-a
co oznacza , że wszystkie - ustanowione i nasłuchujące - i-n
liczbowe - nie próbuj rozstrzygać, powiedzmy,22
nassh
). Następnie wybieramy tylko czwartą kolumnęawk
, która zawiera adres lokalny i port. Używamycut
do dzielenia adresu i portu za pomocą:
separatora i zatrzymywania tylko tego ostatniego (-f2
).ss
wypisujemy również nagłówek, którego pozbywamy się przezgrep
ping dla niepustych ciągów liczb, które nie są dłuższe niż 5. Następnie spełniamycomm
wymaganie poprzezsort
ing bez duplikatów-u
.Teraz mamy posortowaną listę otwartych portów, które możemy
shuf
FLE aby następnie chwycić pierwsze"$HOWMANY"
te zhead -n
.Przykład
Chwyć trzy losowe otwarte porty z zakresu prywatnego (49152-65535)
może na przykład wrócić
Notatki
-t
z-u
INss
aby uzyskać bezpłatne porty UDP zamiast.shuf
zesort -n
jeśli wolisz, aby uzyskać dostępne porty numerycznie posortowane zamiast losowoźródło
Podziękowania dla Chrisa Downa
źródło
Najwyraźniej połączenia TCP mogą być używane jako deskryptory plików w systemie Linux od w bash / zsh. Poniższa funkcja wykorzystuje tę technikę i powinna być szybsza niż wywoływanie netcat / telnet.
Instrukcje użycia: Powiąż dane wyjściowe ze zmienną i użyj w skryptach. Testowane na Ubuntu 16.04
źródło
ksh93
również z .$[$LPORT + ($RANDOM % ($UPORT-$LPORT))]
.\n
do dowolnego portu nasłuchującego :) Sugeruję dodanie-n
. To nadal będzie próbowało otworzyć połączenie, ale niczego nie wyśle, ale natychmiast rozłączy.Oto wieloplatformowy, wydajny „oneliner”, który blokuje wszystkie używane porty i daje pierwszy dostępny od 3000:
Możesz po prostu połączyć wszystkie linie, aby mieć je w jednej linii. Jeśli chcesz uzyskać pierwszy dostępny z innego numeru portu, zmień przypisanie na
i
wfor
pętli.Działa zarówno na Macu, jak i Linuksie, dlatego
[:.]
potrzebny jest regex.źródło
-a
nie-t
patrzeć tylko na gniazda TCP (6)?ss -Htnl
może być lepsze (i szybsze! - nie to, że mnie to obchodzi: P).-t
, przynajmniej ten, który jest dostarczany przez Apple, ass
także nie jest obecny na macOS.netstat -aln
działa nawet w systemie Solaris.W systemie Linux możesz zrobić coś takiego:
Aby znaleźć pierwszy wolny port powyżej 1080. Zauważ, że
ssh -D
wiązałby się on z interfejsem sprzężenia zwrotnego, więc teoretycznie możesz ponownie użyć portu 1080, jeśli gniazdo ma przypisany inny adres. Innym sposobem może być próba powiązania go:źródło
ssh -D
, nie widzę lepszej opcji.-O forward
Opcjassh
nie zwraca błąd, gdy nie do przodu.To jest wersja, której używam:
To polecenie
shuf -n 1 -i 49152-65535
daje „losowy” port w zakresie dynamicznym. Jeśli jest już używany, próbowany jest inny port w tym zakresie.Polecenie
netstat -atun
wyświetla listę wszystkich portów (-a) TCP (-t) i UDP (-u) bez marnowania czasu na określenie nazw hostów (-n).źródło
Jest to część funkcji, którą mam w moim .bashrc, która dynamicznie tworzy tunele SSH i próbuje użyć dowolnego portu w zakresie:
YMMV
źródło
Kolejny bieg do tego starego konia hobby:
Kod ten umożliwia korzystanie z przenośnego czysto
netstat
,egrep
,awk
, i in. Zauważ, że wydawane jest tylko wywołanie zewnętrznych poleceń, aby uzyskać listę zajętych portów na początku. Można zażądać jednego lub więcej wolnych portów:i zacznij od dowolnego portu:
źródło
Moja kombinacja z innych odpowiedzi powyżej. Zdobyć:
Z shuf -n1 bierzemy jedną losową liczbę z zakresu (-i) w / proc / sys / net / ipv4 / ip_local_port_range. shuf potrzebuje składni z myślnikiem, więc używamy tr, aby zmienić tabulację w myślniku.
Następnie użyj netstat, aby pokazać nam wszystkie połączenia (-a) tcp i udp (-u -t) w liczbach (-n), jeśli znajdziemy w tym nasz losowy port $ port (zacznij od: i zakończ w w białym spacji ( \ s), potrzebujemy innego portu i kontynuujmy. W przeciwnym razie (grep -q ma kod powrotu> 0, opuściliśmy pętlę while i ustawiono $ port.
źródło
Jeśli masz wokół siebie pytona, zrobiłbym to:
źródło
Napisałem ten mały skrypt Python2 / 3, który może ci pomóc następnym razem:
https://github.com/sdenel/find-unused-local-port
źródło
Moje zdanie na ten temat ... funkcja próbuje znaleźć
n
kolejne wolne porty:źródło