¿Cuál es la forma más fácil de encontrar un puerto local no utilizado?
Actualmente estoy usando algo similar a esto:
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
Se siente terriblemente indirecto, por lo que me pregunto si hay un camino más simple como una construcción que he echado de menos.
shell
networking
shell-script
netstat
mybuddymichael
fuente
fuente
-n
a netstat y a un grep más selectivo). La forma de hacerlo es intentar abrir un puerto en el modo que necesite y probar con otro si no está disponible.ssh -D
como servidor SOCKS.Respuestas:
Si su aplicación lo admite, puede intentar pasar el puerto 0 a la aplicación. Si su aplicación pasa esto al kernel, el puerto se asignará dinámicamente en el momento de la solicitud y se garantiza que no estará en uso (la asignación fallará si todos los puertos ya están en uso).
De lo contrario, puede hacerlo manualmente. El guión en su respuesta tiene una condición de carrera, la única forma de evitarlo es verificar atómicamente si está abierto intentando abrirlo. Si el puerto está en uso, el programa debería cerrarse con una falla al abrir el puerto.
Por ejemplo, supongamos que está tratando de escuchar con GNU netcat.
fuente
$port
en el programa real como enwhile ...; done; program --port $port
.Mi solución es enlazar al puerto 0, que le pide al núcleo que asigne un puerto desde su ip_local_port_range. Luego, cierre el socket y use ese número de puerto en su configuración.
Esto funciona porque el núcleo no parece reutilizar los números de puerto hasta que sea absolutamente necesario. Los enlaces posteriores al puerto 0 asignarán un número de puerto diferente. Código de Python:
Esto proporciona solo un número de puertos, por ejemplo.
60123
.Ejecute este programa 10 000 veces (debe ejecutarlas simultáneamente) y obtendrá 10 000 números de puerto diferentes. Por lo tanto, creo que es bastante seguro usar los puertos.
fuente
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 }'
Un trazador de líneas
He reunido un buen one-liner que cumple rápidamente el propósito, lo que permite capturar un número arbitrario de puertos en un rango arbitrario (aquí se divide en 4 líneas para facilitar la lectura):
Linea por linea
comm
es una utilidad que compara líneas en dos archivos que deben aparecer ordenadas alfabéticamente. Produce tres columnas: líneas que aparecen solo en el primer archivo, líneas que solo aparecen en el segundo y líneas comunes. Al especificar-23
, suprimimos las últimas columnas y solo conservamos la primera. Podemos usar esto para obtener la diferencia de dos conjuntos, expresados como una secuencia de líneas de texto. Aprendí sobrecomm
aquí .El primer archivo es el rango de puertos que podemos seleccionar.
seq
produce una secuencia ordenada de números de$FROM
a$TO
. El resultado se ordena alfabéticamente (en lugar de numéricamente) y se canalizacomm
como el primer archivo usando la sustitución del proceso .El segundo archivo es la lista ordenada de puertos, que obtenemos al llamar al
ss
comando (con el-t
significado de puertos TCP, que-a
significa todo - establecido y escuchando - y-n
numérico - no intente resolver, digamos,22
assh
). Luego seleccionamos solo la cuarta columna conawk
, que contiene la dirección local y el puerto. Usamoscut
dividir la dirección y el puerto con el:
delimitador y mantener solo el último (-f2
).ss
también genera un encabezado, del cual nos deshacemos haciendogrep
ping para secuencias de números no vacías que no son más largas que 5. Luego cumplimos concomm
el requisito desort
in sin duplicados-u
.Ahora tenemos una lista ordenada de los puertos abiertos, que podemos
shuf
FLE a continuación, apoderarse de los primeros"$HOWMANY"
que tienenhead -n
.Ejemplo
Tome los tres puertos abiertos aleatorios en el rango privado (49152-65535)
podría volver por ejemplo
Notas
-t
con el-u
dess
conseguir los puertos UDP libres en su lugar.shuf
consort -n
si prefiere obtener puertos disponibles ordenados numéricamente en lugar de al azarfuente
Créditos a Chris Down
fuente
Aparentemente, las conexiones TCP se pueden usar como descriptores de archivos en Linux desde bash / zsh. La siguiente función utiliza esa técnica y debería ser más rápida que invocar netcat / telnet.
Instrucciones de uso: enlaza la salida a una variable y úsala en scripts. Probado en Ubuntu 16.04
fuente
ksh93
también.$[$LPORT + ($RANDOM % ($UPORT-$LPORT))]
.\n
embargo, esto se envía a cualquier puerto de escucha :) Sugeriría agregar-n
. Esto aún intentará abrir una conexión pero no enviará nada más que desconectarse inmediatamente.Aquí hay un "oneliner" eficiente y multiplataforma que absorbe todos los puertos en uso y le ofrece el primero disponible desde 3000 en adelante:
Simplemente puede unir todas las líneas para tenerlo en una sola línea. Si desea obtener el primero disponible de un número de puerto diferente, cambie la asignación a
i
en elfor
bucle.Funciona tanto en Mac como en Linux, por eso
[:.]
se necesita la expresión regular.fuente
-a
y no-t
solo mirar los sockets TCP (6)?ss -Htnl
podría ser mejor (¡y más rápido! - no es que me importe eso: P).-t
, al menos con el que Apple incluye, yss
tampoco está presente en macOS.netstat -aln
incluso funciona en Solaris.En Linux, podría hacer algo como:
Para encontrar el primer puerto libre por encima de 1080. Tenga en cuenta que se
ssh -D
uniría a la interfaz de bucle invertido, por lo que, en teoría, podría reutilizar el puerto 1080 si un socket lo tiene vinculado a otra dirección. Otra forma sería tratar de vincularlo:fuente
ssh -D
, no puedo ver ninguna mejor opción. La-O forward
opción dessh
no devuelve un error cuando falla el reenvío.Esta es la versión que uso:
El comando
shuf -n 1 -i 49152-65535
le proporciona un puerto "aleatorio" en el rango dinámico. Si ya se usa, se intenta otro puerto en ese rango.El comando
netstat -atun
enumera todos los puertos (-a) TCP (-t) y UDP (-u) sin perder tiempo para determinar los nombres de host (-n).fuente
Esto es parte de una función que tengo en mi .bashrc, que crea dinámicamente túneles SSH e intenta usar cualquier puerto en un rango:
YMMV
fuente
Otra carrera más en este viejo caballo de pasatiempo:
Este código hace uso puramente portátil de
netstat
,egrep
,awk
, y col. Tenga en cuenta que solo se emite una llamada a comandos externos para obtener una lista de los puertos tomados al principio. Se puede solicitar uno o más puertos libres:y comenzar en un puerto arbitrario:
fuente
Mi combinación de otras respuestas anteriores. Consíguelo:
Con shuf -n1 tomamos un número aleatorio del rango (-i) en / proc / sys / net / ipv4 / ip_local_port_range. shuf necesita la sintaxis con guión, por lo que usamos tr para cambiar la pestaña en un guión.
Luego, use netstat para mostrarnos todas las conexiones (-a) tcp y udp (-u -t) en números (-n), si encontramos nuestro puerto aleatorio $ port en esto (comience con a: y termine con w espacio en blanco ( \ s) entonces necesitamos otro puerto y así continuar. De lo contrario (grep -q tiene un código de retorno> 0, dejamos el bucle while y se establece $ port.
fuente
Si tienes Python por ahí, haría esto:
fuente
Escribí este pequeño script Python2 / 3 que podría ayudarte la próxima vez:
https://github.com/sdenel/find-unused-local-port
fuente
Mi opinión sobre esto ... la función intenta encontrar
n
puertos libres consecutivos:fuente