Estoy buscando un método rápido y simple para probar adecuadamente si un puerto TCP determinado está abierto en un servidor remoto, desde dentro de un script de Shell.
Me las arreglé para hacerlo con el comando telnet, y funciona bien cuando se abre el puerto, pero parece que no se agota el tiempo de espera cuando no lo está y simplemente se cuelga allí ...
Aquí hay una muestra:
l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Necesito una mejor manera, o una forma de forzar el tiempo de espera de telnet si no se conecta en menos de 8 segundos, por ejemplo, y devolver algo que pueda atrapar en Shell (código de retorno o cadena en stdout).
Conozco el método Perl, que usa el módulo IO :: Socket :: INET y escribió un script exitoso que prueba un puerto, pero preferiría evitar usar Perl si es posible.
Nota: Esto es lo que está ejecutando mi servidor (desde donde necesito ejecutar esto)
SunOS 5.10 Generic_139556-08 i86pc i386 i86pc
Respuestas:
Como señaló B. Rhodes,
nc
hará el trabajo. Una forma más compacta de usarlo:De esa manera
nc
solo verificará si el puerto está abierto, saliendo con 0 en caso de éxito, 1 en caso de error.Para una verificación interactiva rápida (con un tiempo de espera de 5 segundos):
fuente
-G#
para establecer un tiempo de espera de conexión separado de / además del-w#
tiempo de espera, que básicamente funciona como un tiempo de espera de lectura.-z
opción. Es posible que desee considerar: unix.stackexchange.com/questions/393762/…Es bastante fácil de hacer con los
-z
y-w TIMEOUT
las opciones anc
, pero no todos los sistemas se hannc
instalado. Si tiene una versión de bash lo suficientemente reciente, esto funcionará:Lo que sucede aquí es que
timeout
ejecutará el subcomando y lo matará si no sale dentro del tiempo de espera especificado (1 segundo en el ejemplo anterior). En este caso,bash
es el subcomando y utiliza su manejo especial / dev / tcp para intentar abrir una conexión al servidor y al puerto especificados. Sibash
puede abrir la conexión dentro del tiempo de espera,cat
simplemente la cerrará inmediatamente (ya que está leyendo/dev/null
) y0
saldrá con un código de estado del cual se propagarábash
y luegotimeout
. Si sebash
produce un error de conexión antes del tiempo de espera especificado,bash
saldrá con un código de salida de 1 quetimeout
también regresará. Y si bash no puede establecer una conexión y el tiempo de espera especificado expira, entoncestimeout
matarábash
y saldrá con un estado de 124.fuente
/dev/tcp
disponible en sistemas que no sean Linux? ¿Qué pasa con las Mac en particular?timeout
que tampoco existe en FreeBSD, y en mi antiguo cuadro de Ubuntu es un paquete instalable, pero no está allí por defecto. Sería genial si hubiera una manera de hacer esto solo en bash, sin herramientas de terceros como timeout o netcat.timeout
parece ser parte de GNU coreutils, y se pueden instalar en los Macs con homebrew:brew install coreutils
. Luego estará disponible comogtimeout
.bash-2.04-devel
, aunque es posible que se haya agregado compatibilidad con los nombres de hostbash-2.05-alpha1
.TOC:
timeout
nc
Usando bash y
timeout
:Tenga en cuenta que
timeout
debería estar presente con RHEL 6+, o alternativamente se encuentra en GNU coreutils 8.22. En MacOS, instálelo usandobrew install coreutils
y úselo comogtimeout
.Mando:
Si parametriza el host y el puerto, asegúrese de especificarlos como
${HOST}
y${PORT}
como se muestra arriba. No los especifique simplemente como$HOST
y$PORT
, es decir, sin las llaves; No funcionará en este caso.Ejemplo:
Éxito:
Fracaso:
Si debe preservar el estado de salida de
bash
,Utilizando
nc
:Tenga en cuenta que
nc
se instala una versión incompatible con versiones anteriores de RHEL 7.Mando:
Tenga en cuenta que el siguiente comando es único, ya que es idéntico tanto para RHEL 6 como para 7. La instalación y la salida son diferentes.
RHEL 6 (nc-1.84):
Instalación:
Ejemplos:
Éxito: Fracaso:Si el nombre de host se asigna a varias direcciones IP, el comando de falla anterior pasará por muchas o todas ellas. Por ejemplo:
RHEL 7 (nmap-ncat-6.40):
Instalación:
Ejemplos:
Éxito: Fracaso:Si el nombre de host se asigna a varias direcciones IP, el comando de falla anterior pasará por muchas o todas ellas. Por ejemplo:
Observaciones:
El argumento
-v
(--verbose
) y elecho $?
comando son, por supuesto, solo ilustrativos.fuente
timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
es un gran punto!2>&1
a estado no ecoresult_test=$(nc -w 2 $ip_addreess 80 </dev/null 2>&1 ; echo $?)
Con
netcat
usted puede verificar si un puerto está abierto así:El valor de retorno de
nc
será exitoso si se abrió el puerto TCP, y fallará (típicamente el código de retorno 1) si no se pudo establecer la conexión TCP.Algunas versiones de
nc
se bloquearán cuando intente esto, ya que no cierran la mitad de envío de su socket incluso después de recibir el fin del archivo/dev/null
. En mi propia computadora portátil Ubuntu (18.04), lanetcat-openbsd
versión de netcat que he instalado ofrece una solución alternativa: la-N
opción es necesaria para obtener un resultado inmediato:fuente
nc
que no son compatibles con la-w
bandera.-z
soporte - funciona en RHEL / CentOS 7, por ejemplo-w
es necesario, si no se puede suspender el comando cuando se usa en un script durante más de diez segundos. He escrito una respuesta que incluye-w
.nc host port -w 2 && echo it works
nc -vz localhost 3306
. Da una salida más detallada. Lo probé solo en mac.En Bash usando archivos de pseudodispositivo para conexiones TCP / UDP es sencillo. Aquí está el guión:
Pruebas:
Aquí hay una línea (sintaxis Bash):
Tenga en cuenta que algunos servidores pueden estar protegidos por firewall de ataques de inundación SYN, por lo que puede experimentar un tiempo de espera de conexión TCP (~ 75 segundos). Para solucionar el problema del tiempo de espera, intente:
Consulte: ¿Cómo disminuir el tiempo de espera de llamadas del sistema TCP connect ()?
fuente
telnet canyouseeme.org 81
también se cuelga. Esto está controlado por los límites de tiempo de espera que probablemente están codificados en bash. Ver: disminuir el tiempo de espera de llamadas del sistema TCP connect () .$SERVER
y$PORT
con llaves, al menos como${SERVER}
y${PORT}
.Necesitaba una solución más flexible para trabajar en múltiples repositorios git, así que escribí el siguiente código sh basado en 1 y 2 . Puede usar la dirección de su servidor en lugar de gitlab.com y su puerto en reemplazo de 22.
fuente
Si está utilizando ksh o bash , ambos admiten la redirección de E / S a / desde un socket utilizando la construcción / dev / tcp / IP / PORT . En este shell Korn ejemplo estoy a redirigir no-op de ( : ) STD-en de un socket:
El shell imprime un error si el socket no está abierto:
Por lo tanto, puede usar esto como prueba en una condición if :
El no-op está en una subshell para que pueda tirar std-err si falla la redirección std-in.
A menudo uso / dev / tcp para verificar la disponibilidad de un recurso a través de HTTP:
Este one-liner abre el descriptor de archivo 9 para leer y escribir en el socket, imprime HTTP GET en el socket y utiliza
cat
para leer desde el socket.fuente
</dev/tcp/canyouseeme.org/80
y luego</dev/tcp/canyouseeme.org/81
.Si bien era una pregunta anterior, acabo de tratar una variante de la misma, pero ninguna de las soluciones aquí era aplicable, así que encontré otra y la agregué para la posteridad. Sí, sé que el OP dijo que estaban al tanto de esta opción y que no era adecuada para ellos, pero para cualquiera que la siguiera podría resultar útil.
En mi caso, quiero probar la disponibilidad de un
apt-cacher-ng
servicio local de unadocker
compilación. Eso significa que no se puede instalar absolutamente nada antes de la prueba. No senc
,nmap
,expect
,telnet
opython
.perl
Sin embargo, está presente, junto con las bibliotecas principales, así que usé esto:fuente
En algunos casos donde las herramientas como curl, telnet, nc o nmap no están disponibles, aún tiene una oportunidad con wget
fuente
verificar puertos usando bash
Ejemplo
el puerto 22 está abierto
Código
fuente
Si desea usar
nc
pero no tiene una versión que admita-z
, intente usar--send-only
:y con tiempo de espera:
y sin búsqueda de DNS si es una IP:
Devuelve los códigos según
-z
si se puede conectar o no.fuente
Supongo que es demasiado tarde para una respuesta, y esta podría no ser una buena, pero aquí tienes ...
¿Qué hay de ponerlo dentro de un bucle while con un temporizador de algún tipo? Soy más un tipo Perl que Solaris, pero dependiendo del shell que estés usando, deberías poder hacer algo como:
Y luego solo agregue una bandera en el ciclo while, de modo que si se agota el tiempo de espera antes de completar, puede citar el tiempo de espera como motivo de falla.
Sospecho que el telnet también tiene un interruptor de tiempo de espera, pero justo fuera de mi cabeza, creo que lo anterior funcionará.
fuente
Necesitaba un script corto que se ejecutara en cron y no haya salido Resuelvo mis problemas usando nmap
Para ejecutarlo, debe instalar nmap porque no es el paquete instalado por defecto.
fuente
nmap
La salida de grepable también puede ser útil-oG -
para enviarla a stdout. (El grep necesitaría un poco de modificación)Esto usa telnet detrás de escena y parece funcionar bien en mac / linux. No usa netcat debido a las diferencias entre las versiones en linux / mac, y esto funciona con una instalación predeterminada de mac.
Ejemplo:
is_port_open.sh
fuente
Sobre la base de la respuesta más votada, esta es una función para esperar a que se abran dos puertos, con un tiempo de espera también. Tenga en cuenta los dos puertos que deben estar abiertos, 8890 y 1111, así como los max_attempts (1 por segundo).
fuente
nmap-ncat para probar el puerto local que aún no está en uso
fuente