Quel est le moyen le plus simple de trouver un port local inutilisé?
Actuellement, j'utilise quelque chose de similaire à ceci:
port=$RANDOM
quit=0
while [ "$quit" -ne 1 ]; do
netstat -a | grep $port >> /dev/null
if [ $? -gt 0 ]; then
quit=1
else
port=`expr $port + 1`
fi
done
Il fait terriblement demi-tour, alors je me demande s’il existe un chemin plus simple, tel qu’un chemin intégré, que j’ai manqué.
shell
networking
shell-script
netstat
mybuddymichael
la source
la source
-n
à netstat et un grep plus sélectif). Pour ce faire, essayez d'ouvrir un port dans le mode dont vous avez besoin et essayez-en un autre s'il n'est pas disponible.ssh -D
un serveur SOCKS.Réponses:
Si votre application le prend en charge, vous pouvez essayer de transmettre le port 0 à l’application. Si votre application transmet cela au noyau, le port sera alloué de manière dynamique au moment de la demande et il sera garanti qu'il ne sera pas utilisé (l'allocation échouera si tous les ports sont déjà utilisés).
Sinon, vous pouvez le faire manuellement. Le script dans votre réponse a une condition de concurrence critique, le seul moyen de l'éviter est de vérifier de manière atomique s'il est ouvert en essayant de l'ouvrir. Si le port est en cours d'utilisation, le programme doit être arrêté avec une incapacité à ouvrir le port.
Par exemple, supposons que vous essayez d'écouter avec GNU netcat.
la source
$port
le programme tel quelwhile ...; done; program --port $port
.Ma solution est de se connecter au port 0, qui demande au noyau d'allouer un port à partir de son ip_local_port_range. Fermez ensuite le socket et utilisez ce numéro de port dans votre configuration.
Cela fonctionne parce que le noyau ne semble pas réutiliser les numéros de port avant que ce ne soit absolument nécessaire. Les liaisons ultérieures au port 0 attribueront un numéro de port différent. Code python:
Cela donne juste un numéro de port, par exemple.
60123
.Exécutez ce programme 10 000 fois (vous devriez les exécuter simultanément) et vous obtiendrez 10 000 numéros de port différents. Par conséquent, je pense que l’utilisation des ports est assez sûre.
la source
python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()'
{ 1: 7006, 2: 1249, 3: 151, 4: 8, 5: 1, 6: 1}
ruby -e 'puts Addrinfo.tcp("", 0).bind { |s| s.local_address.ip_port }'
Bon mot
J'ai mis au point une ligne simple qui répond rapidement à cet objectif, permettant de saisir un nombre arbitraire de ports dans une plage quelconque (ici, il est divisé en 4 lignes pour la lisibilité):
Ligne par ligne
comm
est un utilitaire qui compare les lignes de deux fichiers devant apparaître triés par ordre alphabétique. Il génère trois colonnes: les lignes qui apparaissent uniquement dans le premier fichier, les lignes qui apparaissent uniquement dans le second et les lignes communes. En spécifiant,-23
nous supprimons ces dernières colonnes et ne conservons que la première. Nous pouvons utiliser ceci pour obtenir la différence de deux ensembles, exprimés sous la forme d'une séquence de lignes de texte. J'ai appris à propos decomm
ici .Le premier fichier est la gamme de ports que nous pouvons sélectionner.
seq
produit une séquence triée de nombres allant de$FROM
à$TO
. Le résultat est trié par ordre alphabétique (au lieu de numérique) et dirigé verscomm
le premier fichier en utilisant la substitution de processus .Le deuxième fichier est la liste triée des ports, obtenue en appelant la
ss
commande (ce qui-t
signifie ports TCP,-a
signifiant tout établi et à l'écoute - et-n
numérique - n'essayez pas de résoudre, par exemple,22
enssh
). Nous sélectionnons ensuite uniquement la quatrième colonneawk
contenant l’adresse locale et le port. Nous avons l'habitudecut
de scinder l'adresse et le port avec le:
délimiteur et de ne garder que celui-ci (-f2
).ss
génère également un en-tête, que nous éliminons pargrep
ping pour les séquences non vides de nombres ne dépassant pas 5. Nous nous conformons ensuite àcomm
l'exigence de ssort
en dupliquant-u
.Maintenant , nous avons une liste triée des ports ouverts, que nous pouvons
shuf
FLE pour saisir ensuite les premiers"$HOWMANY"
ceux avechead -n
.Exemple
Saisissez les trois ports ouverts aléatoires dans la plage privée (49152-65535)
pourrait revenir par exemple
Remarques
-t
avec-u
dansss
pour obtenir des ports UDP libres à la place.shuf
parsort -n
si vous préférez avoir les ports disponibles triés numériquement plutôt que de façon aléatoirela source
Crédits à Chris Down
la source
Apparemment, les connexions TCP peuvent être utilisées comme descripteurs de fichiers sous Linux à partir de avec bash / zsh. La fonction suivante utilise cette technique et devrait être plus rapide que d'appeler netcat / telnet.
Instructions d'utilisation: Liez le résultat à une variable et utilisez-le dans des scripts. Testé sur Ubuntu 16.04
la source
ksh93
aussi.$[$LPORT + ($RANDOM % ($UPORT-$LPORT))]
.\n
à n’importe quel port d’écoute :) Je suggère d’ajouter-n
. Ceci essayera toujours d'ouvrir une connexion mais n'enverra rien mais déconnectera immédiatement.Voici un "oneliner" multi-plateforme et efficace qui sillonne tous les ports utilisés et vous donne le premier disponible à partir de 3000:
Vous pouvez simplement joindre toutes les lignes pour l’avoir sur une seule ligne. Si vous souhaitez obtenir le premier disponible à partir d'un numéro de port différent, modifiez l'affectation en
i
dans lafor
boucle.Cela fonctionne à la fois sur Mac et Linux, c'est pourquoi la
[:.]
regex est nécessaire.la source
-a
et ne-t
pas simplement regarder les sockets TCP (6)?ss -Htnl
pourrait être meilleur (et plus rapide! - pas que je me soucie de ça: P).-t
, du moins celui fourni par Apple, etss
n'est pas présent non plus sur macOS.netstat -aln
fonctionne même sur Solaris.Sous Linux, vous pouvez faire quelque chose comme:
Pour trouver le premier port libre supérieur à 1080. Notez que la
ssh -D
liaison serait liée à l'interface de bouclage. En théorie, vous pouvez donc réutiliser le port 1080 si un socket l'a lié à une autre adresse. Une autre façon serait d'essayer de le lier:la source
ssh -D
, je ne vois pas de meilleure option. L'-O forward
option dessh
ne renvoie pas d'erreur lorsque le transfert échoue.Ceci est la version que j'utilise:
La commande
shuf -n 1 -i 49152-65535
vous donne un port "aléatoire" dans la plage dynamique. S'il est déjà utilisé, un autre port de cette gamme est essayé.La commande
netstat -atun
répertorie tous les ports (-a) TCP (-t) et UDP (-u) sans perdre de temps à déterminer les noms d'hôte (-n).la source
Cela fait partie d'une fonction que j'ai dans mon .bashrc, qui crée dynamiquement des tunnels SSH et tente d'utiliser n'importe quel port dans une plage:
YMMV
la source
Encore une autre course à ce vieux cheval de bataille:
Ce code utilise purement portable
netstat
,egrep
,awk
, et al. Notez que seul l'appel est émis vers les commandes externes, pour obtenir une liste des ports pris au début. On peut demander un ou plusieurs ports libres:et commencez à un port arbitraire:
la source
Ma combinaison d'autres réponses ci-dessus. Tu piges:
Avec shuf -n1, nous prenons un nombre aléatoire de la plage (-i) dans / proc / sys / net / ipv4 / ip_local_port_range. shuf a besoin de la syntaxe avec dash, nous utilisons donc tr pour changer de tabulation dans un tiret.
Nous utiliserons ensuite netstat pour nous montrer toutes les connexions (-a) tcp et udp (-u -t) en nombres (-n), si nous trouvons notre port aléatoire $ port dans cet emplacement (commençons par a: et finissons par w espaces blancs ( \ s) alors nous avons besoin d’un autre port et nous continuons ainsi. Sinon (grep -q a un code retour> 0 nous avons laissé la boucle while et $ port est défini
la source
Si vous avez du python, je le ferais:
la source
J'ai écrit ce petit script Python2 / 3 qui pourrait vous aider la prochaine fois:
https://github.com/sdenel/find-unused-local-port
la source
Mon point de vue ... la fonction essaie de trouver
n
des ports libres consécutifs:la source