El comando de Linux obtiene un puerto no utilizado

20

Estoy buscando un comando o script que devuelva un puerto no utilizado en mi sistema ubuntu linux. He buscado en internet y lo único que encuentro es sobre el puerto usado / Listen con el comando nestat. Aparentemente, algo con el comando netstat funcionará, pero no sé qué exactamente. ¿Alguna idea de cómo?

Gracias.

usuario2429082
fuente
1
¿Por qué necesitas hacer eso exactamente? Si está desarrollando un servidor, puede vincularse al puerto 0 y el sistema operativo le asignará un puerto libre, no tiene nada que buscar. De lo contrario, la búsqueda y el enlace son propensos a las condiciones de carrera. Ver por ejemplo stackoverflow.com/questions/1365265/… o stackoverflow.com/questions/1075399/…
Patrick Mevzek

Respuestas:

14

netstat -latda la lista completa de puertos de escucha y establecidos .

Cuando un puerto no está en ninguno de esos estados, no existe para el sistema, por lo que no encontrará un comando que muestre la lista de puertos no utilizados.

Tenga en cuenta que hay 65535 puertos, por lo que todo lo que no netstat -latestá encendido es un puerto no utilizado.

El siguiente script bash hará un escaneo simple de los puertos tcp y le informará cuáles están abiertos y cuáles están cerrados :

#!/bin/bash
IP=$1
first_port=$2
last_port=$3
function scanner

{
for ((port=$first_port; port<=$last_port; port++))
        do
                (echo >/dev/tcp/$IP/$port)> /dev/null 2>&1 && echo $port open || echo "$port closed"
        done
}

scanner

Si lo guarda como portscan.sh , debe ejecutarse como ./portscan.sh IP first_port last_port , por ejemplo: ./portscan 127.0.0.1 20 135escaneará el equipo local desde los puertos 20 a 135

jcbermu
fuente
7

Ruby 2.x (una línea):

ruby -e 'require "socket"; puts Addrinfo.tcp("", 0).bind {|s| s.local_address.ip_port }'

En mi máquina ahora mismo que impreso:

42644

Una invocación posterior impresa:

36168

Esta técnica hace que el usuario actual solicite un puerto no utilizado (enlace al puerto "0") y luego imprime el número de puerto que proporcionó el sistema operativo. Y dado que el usuario actual es el que pregunta, los puertos por debajo de 1024 no se devolverán (a menos que el usuario actual = root).

Crédito donde el crédito es debido: esta solución proviene de un comentario de Franklin Yu en unix.stackexchange.com ¿Cuál es la forma más fácil de encontrar un puerto local no utilizado?

G. Sylvie Davies
fuente
¿Cómo podría asignar el resultado de esto a una variable en un script bash?
Neil Stevens
export PORT = $ (ruby -e 'require "socket"; pone Addrinfo.tcp ("", 0) .bind {| s | s.local_address.ip_port}')
G. Sylvie Davies
3

Secuencia de comandos de bash corta que genera aleatoriamente un número entre 1025 y 60000 y se repite hasta que ese número no se encuentra en la lista de puertos utilizados. Esta es una solución rápida y sucia que tiene un sesgo hacia puertos más grandes:

CHECK="do while"

while [[ ! -z $CHECK ]]; do
    PORT=$(( ( RANDOM % 60000 )  + 1025 ))
    CHECK=$(sudo netstat -ap | grep $PORT)
done

echo $PORT
Taras
fuente
Verifique su comando grep, vea el comentario sobre la respuesta de adarshr
Nick
2

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):

comm -23 \
<(seq "$FROM" "$TO") \
<(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep '[0-9]\{1,5\}' | sort -n | uniq) \
| shuf | head -n "$HOWMANY"

Linea por linea

commes una utilidad que compara líneas ordenadas en dos archivos. 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í sobre comm aquí .

El primer archivo es el rango de puertos que podemos seleccionar. seqproduce una secuencia ordenada de números de $FROMa $TO. El resultado se canaliza commcomo el primer archivo que usa la sustitución del proceso .

El segundo archivo es la lista ordenada de puertos, que obtenemos al llamar al sscomando (con el -tsignificado de puertos TCP, que -asignifica todo - establecido y escuchando - y -nnumérico - no intente resolver, digamos, 22a ssh). Luego seleccionamos solo la cuarta columna con awk, que contiene la dirección local y el puerto. Usamos cutdividir la dirección y el puerto con el :delimitador y mantener solo el último ( -f2). sstambién genera un encabezado, que eliminamos haciendo grepping para secuencias de números no vacías que no son más largas que 5. Luego cumplimos con commel requisito al sortingresar numéricamente ( -n) y eliminar los duplicados con uniq.

Ahora tenemos una lista ordenada de los puertos abiertos, que podemos shufFLE a continuación, apoderarse de los primeros "$HOWMANY"que tienen head -n.

Ejemplo

Tome los tres puertos abiertos aleatorios en el rango privado (49152-65535)

comm -23 <(seq 49152 65535) <(ss -tan | awk '{print $4}' | cut -d':' -f2 | grep "[0-9]\{1,5\}" | sort | uniq) | shuf | head -n 3

podría volver por ejemplo

54930
57937
51399

Notas

  • cambiar -tcon el -ude ssconseguir los puertos UDP libres en su lugar.
  • suelte shufsi no está interesado en tomar un puerto aleatorio
stefanobaghino
fuente
1
Me gusta su one-liner, esta versión analiza correctamente IPv6, por ejemplo [:: 1]: 52792 y usa la opción --no-header en lugar de grep. gist.github.com/fstefanov/ff4dcec7ded59514421bf944d1bb9a6f
Filip Stefanov
1

Necesitaba encontrar solo un puerto aleatorio no utilizado y no imprimir una lista de ellos. Aquí está mi solución bash.

#/bin/bash

function random_unused_port {
    local port=$(shuf -i 2000-65000 -n 1)
    netstat -lat | grep $port > /dev/null
    if [[ $? == 1 ]] ; then
        export RANDOM_PORT=$port
    else
        random_unused_port
    fi
}

random_unused_port

Y úsalo comprándolo

$ . ./random_unused_port.sh; echo $RANDOM_PORT
adarshr
fuente
Me gusta la idea aquí, sin embargo, su comando grep no devolverá lo que pretende. Lo bueno es que será conservador, pero si el próximo puerto aleatorio es 2000 y el puerto 2000 está abierto, pero el puerto 20000 está en uso, seguirá buscando, por lo que el resultado no será la gama completa de puertos disponibles.
Nick
1

Quizás otra solución basada en la lista de puertos usados:

function random_unused_port {
   (netstat --listening --all --tcp --numeric | 
    sed '1,2d; s/[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*[[:space:]]*[^[:space:]]*:\([0-9]*\)[[:space:]]*.*/\1/g' |
    sort -n | uniq; seq 1 1000; seq 1 65535
    ) | sort -n | uniq -u | shuf -n 1
}

RANDOM_PORT=$(random_unused_port)

El netstatcomando genera una lista de todos los puertos abiertos. El sedcomando extrae los números de puerto, que están en uso y sort/ uniqconstruct devuelve una lista uniq de puertos abiertos. El segundo paso es generar una lista de números de puerto que comiencen en 1 y terminen en 1000 (puertos reservados) y una lista adicional de todos los números de puerto que comiencen en 1 hasta 65535. La lista final contiene todos los puertos disponibles solo una vez y los uniq -uextraerá . Por último, shuf -n 1seleccionará un puerto aleatorio de la lista completa de puertos disponibles. Sin embargo, habrá una condición de carrera, antes de poder reservar el puerto.

Frank Förster
fuente
1

Necesitaba encontrar el siguiente puerto abierto a partir de un número de puerto; Aquí está mi intento de usar la solución de @Taras.

_check="placeholder"
START_FROM=1900
PORT=$(( ( "$RANDOM" % 1000 ) + $START_FROM ))
while [[ ! -z "${_check}" ]]; do
    ((PORT++))
    _check=$(ss -tulpn | grep ":${PORT}")
done
Alberto Chiusole
fuente
0

Si 54321 es su puerto, ejecute:

sudo netstat -ap |grep 54321

Algunas variaciones del uso de netstat se pueden encontrar aquí .

Overmind
fuente
Este comando solo me mostrará si el puerto 54321 se usa o no. Lo que quiero es encontrar el puerto no utilizado.
user2429082
Sin usar es ambiguo. ¿Desea verificar qué puerto está disponible para escuchar? ¿O a qué puerto están disponibles para conectarse? Cualquiera que no esté en uso está disponible. Como usuario, puede usar los que están por encima de 1024, como root, puede usar también los que están por debajo de 1024.
Overmind