Comment dire à un script d'attendre qu'un processus commence à accepter les demandes sur un port?

33

J'ai besoin d'une commande qui attend qu'un processus commence à accepter les demandes sur un port spécifique.

Y at-il quelque chose dans linux qui fait ça?

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

...
Volonté
la source

Réponses:

52

Le meilleur test pour voir si un serveur accepte des connexions est d'essayer de se connecter. Utilisez un client standard quel que soit le protocole utilisé par votre serveur et essayez une commande no-op.

Si vous voulez un client TCP ou UDP léger que vous pouvez piloter simplement à partir du shell, utilisez netcat . Comment programmer une conversation dépend du protocole; sur de nombreux protocoles, le serveur ferme la connexion sur une certaine entrée et netcat se ferme ensuite.

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

Vous pouvez également dire à netcat de quitter après avoir établi la connexion. Il retourne 1 s'il n'y a pas de connexion et 0 s'il y en a, nous nions sa sortie. Selon votre version de netcat, il peut prendre en charge l’une ou les deux commandes suivantes:

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

Une autre approche consiste à attendre que le processus serveur ouvre un socket en écoute.

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

Si vous utilisez Mac OS, netstat utilise un format de sortie légèrement différent. Vous voudrez donc de lire les informations suivantes:

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

Ou vous voudrez peut-être cibler un ID de processus spécifique:

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

Je ne vois aucun moyen de réagir au processus qui commence à écouter le socket (ce qui éviterait une approche par sondage) sans utiliser ptrace.

Gilles, arrête de faire le mal
la source
Je pense que netcat est la solution, alors merci. Pour clarifier, j'essaie d'écrire un script dans le cadre d'une procédure d'équilibrage de charge. Je dois démarrer un processus, attendre qu'il accepte les demandes sur le port, puis arrêter l'original. S'il y a de meilleures façons de le faire, plutôt que d'écrire mon propre script, je suis tout ouïe.
Will
@ Will: C'est une question très différente! J'ai écrit une réponse différente.
Gilles, arrête de faire le mal '31
1
J'aime aussi la solution netcat. J'ai un script qui utilise nc -w 2 </dev/null >/dev/null- si la connexion prend plus de 2 secondes, il expire et échoue - ce qui est pratique pour mon utilisation.
éphémère
Pour votre information, je ne peux pas obtenir le 'tant que nc -q 1 localhost 13000 </ dev / null; dormez 10; fait 'un pour travailler. Ça revient tout de suite. Le premier fonctionne bien cependant. Merci!
Ellis Percival
@Flyte nc -q 1 localhost 13000 </dev/nullretourne immédiatement si aucun serveur n'écoute, mais avec un code d'erreur, la boucle la met en veille et réessaye quelques secondes plus tard.
Gilles, arrête de faire le mal. »
17

Si vous avez bash et coreutils (par exemple, timeout, sleep), mais pas nc / lsof / netstat, vous pouvez utiliser cette solution qui utilise les sockets bash tcp magic:

while ! timeout 1 bash -c "echo > /dev/tcp/localhost/13000"; do sleep 10; done
Kanaka
la source
Pour élaborer, Bash a la fonctionnalité optionnelle de se connecter aux sockets TCP en utilisant des "redirections de réseau" - gnu.org/software/bash/manual/html_node/…
johntellsall
7

Après l' exemple précédent avec bashtcp sockets magic, voici une version améliorée qui attend la connexion pendant un temps limité.

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

La différence est que si la connexion n’était pas disponible au cours de 15s, elle ne sera pas bouclée indéfiniment, mais sera fermée avec le code d’erreur.

Ceci est utile dans les scripts d'init pour attendre la disponibilité / disponibilité du service après le démarrage.

arma
la source