346 votes

Comment tester si un port TCP distant est ouvert à partir du Shell script ?

Je cherche une méthode simple et rapide pour tester correctement si un port TCP donné est ouvert sur un serveur distant, depuis l'intérieur d'un script Shell.

J'ai réussi à le faire avec la commande telnet, et cela fonctionne bien lorsque le port est ouvert, mais il ne semble pas y avoir de délai d'attente lorsqu'il ne l'est pas et il reste là....

En voici un exemple :

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

J'ai besoin d'un meilleur moyen, ou d'un moyen de forcer telnet à dépasser le délai d'attente s'il ne se connecte pas en moins de 8 secondes par exemple, et à retourner quelque chose que je peux attraper dans Shell (code de retour, ou chaîne dans stdout).

Je connais la méthode Perl, qui utilise le module IO::Socket::INET et a écrit un script réussi qui teste un port, mais j'aimerais plutôt éviter d'utiliser Perl si possible.

Note : C'est ce que mon serveur exécute (d'où je dois exécuter ceci)

SunOS 5.10 Generic_139556-08 i86pc i386 i86pc

Toute aide serait appréciée !

501voto

meden Points 1397

Comme l'a souligné B. Rhodes, nc fera l'affaire. Une façon plus compacte de l'utiliser :

nc -z <host> <port>

De cette façon nc vérifiera seulement si le port est ouvert, en sortant avec 0 en cas de succès, 1 en cas d'échec.

Pour une vérification interactive rapide (avec un délai de 5 secondes) :

nc -z -w5 <host> <port>; echo $?

185voto

onlynone Points 472

C'est assez facile à faire avec le -z y -w TIMEOUT options pour nc mais tous les systèmes ne disposent pas de nc installé. Si vous avez une version assez récente de bash, cela fonctionnera :

# Connection successful:
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/80'
$ echo $?
0

# Connection failure prior to the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/sfsfdfdff.com/80'
bash: sfsfdfdff.com: Name or service not known
bash: /dev/tcp/sfsfdfdff.com/80: Invalid argument
$ echo $?
1

# Connection not established by the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/81'
$ echo $?
124

Ce qui se passe ici, c'est que timeout exécutera la sous-commande et la tuera si elle ne se termine pas dans le délai spécifié (1 seconde dans l'exemple ci-dessus). Dans ce cas bash est la sous-commande et utilise sa fonction spéciale Traitement de /dev/tcp pour essayer d'ouvrir une connexion au serveur et au port spécifiés. Si bash peut ouvrir la connexion dans le délai imparti, cat le fermera immédiatement (puisqu'il lit à partir de /dev/null ) et sortir avec un code d'état de 0 qui se propagera à travers bash et ensuite timeout . Si bash reçoit un échec de connexion avant le délai spécifié, alors bash se terminera avec un code de sortie de 1 qui timeout sera également retourné. Et si bash n'est pas en mesure d'établir une connexion et que le délai spécifié expire, alors timeout tuera bash et quitter avec un statut de 124.

126voto

A-B-B Points 797

Comando :

nc -v -z -w <timemout_seconds> <host> <port>; echo $?

Référence : man nc

Exemples :

$ nc -v -z -w 3 stackoverflow.com 80; echo $?
Connection to stackoverflow.com 80 port [tcp/http] succeeded!
0

$ nc -v -z -w 3 stackoverflow.com 81; echo $?
nc: connect to stackoverflow.com port 81 (tcp) timed out: Operation now in progress
1

Si vous n'avez pas nc installé, vous pouvez l'installer sur les saveurs Red Hat de Linux en utilisant yum install nc .

Crédit : meden para comando .

63voto

Brandon Rhodes Points 21188

Avec netcat, vous pouvez vérifier si un port est ouvert comme ceci :

nc my.host.com 80 < /dev/null

La valeur de retour de nc sera un succès si le port TCP a été ouvert, et un échec (généralement le code de retour 1) s'il n'a pas pu établir la connexion TCP.

12voto

merebagatelle Points 41

Si vous utilisez ksh o bash ils supportent tous les deux la redirection des entrées/sorties vers/depuis une socket en utilisant la fonction /dev/tcp/IP/PORT construire. Dans ce Shell Korn Dans l'exemple, je redirige les no-op's ( : ) std-in à partir d'une prise :

W$ python -m SimpleHTTPServer &
[1]     16833
Serving HTTP on 0.0.0.0 port 8000 ...
W$ : </dev/tcp/127.0.0.1/8000

Le shell imprime une erreur si la socket n'est pas ouverte :

W$ : </dev/tcp/127.0.0.1/8001
ksh: /dev/tcp/127.0.0.1/8001: cannot open [Connection refused]

Vous pouvez donc l'utiliser comme test dans un si condition :

SERVER=127.0.0.1 PORT=8000
if (: < /dev/tcp/$SERVER/$PORT) 2>/dev/null
then
    print succeeded
else
    print failed
fi

Le no-op est dans un sous-shell afin que je puisse jeter std-err si la redirection std-in échoue.

J'utilise souvent /dev/tcp pour vérifier la disponibilité d'une ressource sur HTTP :

W$ print arghhh > grr.html
W$ python -m SimpleHTTPServer &
[1]     16863
Serving HTTP on 0.0.0.0 port 8000 ...
W$ (print -u9 'GET /grr.html HTTP/1.0\n';cat <&9) 9<>/dev/tcp/127.0.0.1/8000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.6.1
Date: Thu, 14 Feb 2013 12:56:29 GMT
Content-type: text/html
Content-Length: 7
Last-Modified: Thu, 14 Feb 2013 12:55:44 GMT

arghhh
W$ 

Cette phrase ouvre descripteur de fichier 9 pour la lecture et l'écriture dans le socket, et imprime le fichier HTTP GET à la prise et utilise chat pour lire depuis le socket.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X