¿Cómo le digo a un script que espere a que un proceso comience a aceptar solicitudes en un puerto?


33

Necesito un comando que espere a que un proceso comience a aceptar solicitudes en un puerto específico.

¿Hay algo en Linux que haga eso?

while (checkAlive -host localhost -port 13000 == false)
  do some waiting

...

Respuestas:


52

La mejor prueba para ver si un servidor está aceptando conexiones es intentar realmente conectarse. Use un cliente normal para cualquier protocolo que hable su servidor y pruebe un comando no-op.

Si desea un cliente TCP o UDP ligero que pueda manejar simplemente desde el shell, use netcat . Cómo programar una conversación depende del protocolo; muchos protocolos hacen que el servidor cierre la conexión en una determinada entrada, y netcat se cerrará.

while ! echo exit | nc localhost 13000; do sleep 10; done

También puede decirle a netcat que salga después de establecer la conexión. Devuelve 1 si no hay conexión y 0 si la hay, por lo que negamos su salida. Dependiendo de su versión de netcat, puede admitir uno o ambos de los siguientes comandos:

while ! nc -z localhost 13000 </dev/null; do sleep 10; done
while ! nc -q 1 localhost 13000 </dev/null; do sleep 10; done

Un enfoque alternativo es esperar a que el proceso del servidor abra un socket de escucha.

while netstat -lnt | awk '$4 ~ /:13000$/ {exit 1}'; do sleep 10; done

Si estás en Mac OS, netstat usa un formato de salida ligeramente diferente, por lo que querrás el siguiente intead:

while netstat -lnt | awk '$4 ~ /\.13000$/ {exit 1}'; do sleep 10; done

O es posible que desee orientar un ID de proceso específico:

while ! lsof -n -Fn -p $pid | grep -q '^n.*:13000$'; do sleep 10; done

No se me ocurre ninguna forma de reaccionar ante el proceso que comienza a escuchar el socket (lo que evitaría un enfoque de sondeo) sin usar ptrace.


Creo que netcat es la respuesta, así que gracias. Para aclarar, lo que estoy tratando de hacer es escribir un script como parte de un procedimiento de equilibrio de carga. Necesito iniciar un proceso, esperar a que acepte solicitudes en el puerto y luego apagar el original. Si hay mejores formas de hacerlo, en lugar de escribir mi propio guión, soy todo oídos.
Se

@Will: ¡Esa es una pregunta muy diferente! He escrito una respuesta diferente.
Gilles 'SO- deja de ser malvado'

1
También me gusta la solución netcat. Tengo un script que usa nc -w 2 </dev/null >/dev/null, si la conexión tarda más de 2 segundos, se agota el tiempo de espera y falla, lo cual es útil para mi uso.
Ephemient

FYI, no puedo obtener el 'while nc -q 1 localhost 13000 </ dev / null; duerme 10; hecho 'uno para trabajar. Simplemente regresa de inmediato. Sin embargo, el primero funciona bien. ¡Gracias!
Ellis Percival

@Flyte nc -q 1 localhost 13000 </dev/nullregresa inmediatamente si no hay ningún servidor escuchando, pero regresa con un código de error, por lo que el bucle lo hace dormir e intenta nuevamente unos segundos más tarde.
Gilles 'SO- deja de ser malvado'

17

Si tiene bash y coreutils (por ejemplo, tiempo de espera, suspensión), pero no nc / lsof / netstat, puede usar esta solución que usa bash magic tcp sockets:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done

Para elaborar, Bash tiene la función opcional de conectarse a los sockets TCP utilizando "redirecciones de red" - gnu.org/software/bash/manual/html_node/…
johntellsall

7

Siguiendo el ejemplo anterior con bashtcp sockets magic, aquí hay una versión mejorada que espera la conexión durante un tiempo limitado.

timeout 15 bash -c 'until echo > /dev/tcp/localhost/13000; do sleep 0.5; done'

La diferencia es que si la conexión no estuvo disponible durante 15s, no se repetirá para siempre, sino que saldrá con el código de error.

Esto es útil en los scripts de inicio para esperar la disponibilidad / disponibilidad del servicio después del inicio.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.