Comment puis-je écrire un script linux bash qui me dit quels ordinateurs sont allumés sur mon réseau local?
Cela aiderait si je pouvais lui donner en entrée une plage d'adresses IP.
Je suggérerais d'utiliser l'indicateur de ping-scan de nmap,
$ nmap -sn 192.168.1.60-70
Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2009-04-09 20:13 BST
Host machine1.home (192.168.1.64) appears to be up.
Host machine2.home (192.168.1.65) appears to be up.
Nmap finished: 11 IP addresses (2 hosts up) scanned in 0.235 seconds
Cela dit, si vous voulez l'écrire vous-même (ce qui est assez juste), voici comment je le ferais:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
..et une explication de chaque bit de la commande ci-dessus:
Vous pouvez utiliser la syntaxe {1..10}
pour générer une liste de nombres, par exemple.
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
(C'est aussi utile pour des choses comme mkdir {dir1,dir2}/{sub1,sub2}
- ce qui donne dir1
et dir2
, chacun contenant sub1
et sub2
)
Donc, pour générer une liste d'adresses IP, nous ferions quelque chose comme
$ echo 192.168.1.{1..10}
192.168.1.1 192.168.1.2 [...] 192.168.1.10
Pour effectuer une boucle sur quelque chose dans bash, vous utilisez for
:
$ for thingy in 1 2 3; do echo $thingy; done
1
2
3
Ensuite, ping. La commande ping varie un peu selon les systèmes d'exploitation, les distributions/versions (j'utilise actuellement OS X).
Par défaut (à nouveau, sur la version ping
de OS X), il enverra une requête ping jusqu'à ce qu'il soit interrompu, ce qui ne fonctionnera pas. ping -c 1
n'essayera d'envoyer qu'un seul paquet, ce qui devrait suffire à déterminer si une machine est opérationnelle.
Un autre problème est la valeur de délai d'attente, qui semble être de 11 secondes sur cette version de ping .. Elle a été modifiée à l'aide de l'indicateur -t
. Une seconde devrait suffire pour voir si une machine du réseau local est en activité ou non.
Donc, la commande ping que nous allons utiliser est ..
$ ping -c 1 -t 1 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
--- 192.168.1.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
Ensuite, nous devons savoir si la machine a répondu ou non.
Nous pouvons utiliser l'opérateur &&
pour exécuter une commande si la première réussit, par exemple:
$ echo && echo "It works"
It works
$ nonexistantcommand && echo "This should not echo"
-bash: nonexistantcommand: command not found
Bien, alors on peut faire ..
ping -c 1 -t 1 192.168.1.1 && echo "192.168.1.1 est en place!"
L'autre solution consisterait à utiliser le code de sortie de ping .. La commande ping se ferme avec le code de sortie 0 (succès) s'il fonctionne, et un code différent de zéro s'il échoue. En bash, vous obtenez le dernier code de sortie des commandes avec la variable $?
Donc, pour vérifier si la commande fonctionnait, nous le ferions ..
ping -c 1 -t 1 192.168.1.1;
if [ $? -eq 0 ]; then
echo "192.168.1.1 is up";
else
echo "ip is down";
fi
Dernière chose, nous n'avons pas besoin de voir la sortie du ping. Nous pouvons donc rediriger stdout
vers /dev/null
avec la redirection >
, par exemple:
$ ping -c 1 -t 1 192.168.1.1 > /dev/null && echo "IP is up"
IP is up
Et pour rediriger stderr
(pour supprimer les messages ping: sendto: Host is down
), vous utilisez 2>
- par exemple:
$ errorcausingcommand
-bash: errorcausingcommand: command not found
$ errorcausingcommand 2> /dev/null
$
Donc, pour combiner tout ça ..
for ip in 192.168.1.{1..10}; do # for loop and the {} operator
ping -c 1 -t 1 192.168.1.1 > /dev/null 2> /dev/null # ping and discard output
if [ $? -eq 0 ]; then # check the exit code
echo "${ip} is up" # display the output
# you could send this to a log file by using the >>pinglog.txt redirect
else
echo "${ip} is down"
fi
done
Ou, en utilisant la méthode &&
, dans une ligne:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
C'est lent .. Chaque commande ping prend environ 1 seconde (puisque nous avons défini l'indicateur -t timeout sur 1 seconde). Il ne peut exécuter qu'une seule commande ping à la fois. La solution évidente consiste à utiliser des threads. Vous pouvez donc exécuter des commandes simultanées, mais cela va au-delà de ce que vous devriez utiliser bash.
"Les threads Python - un premier exemple" explique comment utiliser le module de threading Python pour écrire un ping'er multi-thread. Bien que, à ce stade, je suggère à nouveau d'utiliser nmap -sn
..
Dans le monde réel, vous pouvez utiliser nmap pour obtenir ce que vous voulez.
nmap -sn 10.1.1.1-255
Cela envoie une requête ping à toutes les adresses comprises entre 10.1.1.1 et 10.1.1.255 et vous permet de savoir lesquelles répondent.
Bien sûr, si vous voulez réellement faire cela comme exercice bash, vous pouvez exécuter un ping pour chaque adresse et analyser le résultat, mais c'est une toute autre histoire.
En supposant que mon réseau est 10.10.0.0/24, si je lance un ping sur l'adresse de diffusion comme
ping -b 10.10.0.255
Je vais obtenir une réponse de tous les ordinateurs de ce réseau qui n'ont pas bloqué leur port de ping ICMP.
64 bytes from 10.10.0.6: icmp_seq=1 ttl=64 time=0.000 ms
64 bytes from 10.10.0.12: icmp_seq=1 ttl=64 time=0.000 ms
64 bytes from 10.10.0.71: icmp_seq=1 ttl=255 time=0.000 ms
Il suffit donc d'extraire la 4ème colonne, avec awk par exemple:
ping -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }'
10.10.0.12:
10.10.0.6:
10.10.0.71:
10.10.0.95:
Eh bien, vous obtiendrez un doublon et il vous faudra peut-être supprimer le «:».
EDIT from comments: L'option -c limite le nombre de pings Puisque le script se terminera, nous pouvons également nous limiter aux adresses IP uniques
ping -c 5 -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }' | sort | uniq
Il y a aussi fping :
fping -g 192.168.1.0/24
ou:
fping -g 192.168.1.0 192.168.1.255
ou ne montrer que les hôtes qui sont en vie:
fping -ag 192.168.1.0/24
Il envoie une requête ping aux hôtes en parallèle, de sorte que l'analyse est très rapide. Je ne connais pas de distribution qui inclut fping
dans son installation par défaut mais dans la plupart des distributions, vous pouvez l'obtenir via le gestionnaire de paquets.
En utilisant également la méthode "cingler l'adresse de diffusion" indiquée par chburd, ce tuyau devrait vous aider:
ping -c 5 -b 10.11.255.255 | sed -n 's/.* \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p' | sort | uniq
Bien sûr, il vous faudrait changer l'adresse de diffusion pour celle de votre réseau.
Si vous vous limitez à ne changer que le dernier octet, ce script devrait le faire. Il devrait être assez évident de savoir comment l’étendre de un à plusieurs octets.
#! /bin/bash BASE=$1 START=$2 END=$3 counter=$START while [$ counter -le $ END] faire ip = $ BASE. $ counter si ping -qc 2 $ ip puis echo "$ ip répond" Fi counter = $ (($ counter + 1)) done
Comme d'autres afficheurs l'ont souligné, nmap
est la voie à suivre, mais voici comment faire l'équivalent d'un scan de ping dans bash. Je n'utiliserais pas le ping de diffusion, car de nombreux systèmes sont configurés pour ne pas répondre à la diffusion ICMP de nos jours.
for i in $(seq 1 254); do
Host="192.168.100.$i"
ping -c 1 -W 1 $Host &> /dev/null
echo -n "Host $Host is "
test $? -eq 0 && echo "up" || echo "down"
done
Certaines machines ne répondent pas aux pings (par exemple les pare-feu).
Si vous ne voulez que le réseau local, vous pouvez utiliser cette commande:
(for n in $(seq 1 254);do Sudo arping -c1 10.0.0.$n & done ; wait) | grep reply | grep --color -E '([0-9]+\.){3}[0-9]+'
arping
est une commande qui envoie des demandes ARP. Il est présent sur la plupart des linux. Exemple:
Sudo arping -c1 10.0.0.14
le Sudo n'est pas nécessaire si vous êtes root ofc.
10.0.0.14
: l'ip que vous voulez tester-c1
: n'envoie qu'une demande.&
: le caractère «je ne veux pas attendre»C'est un personnage vraiment utile qui vous donne la possibilité de lancer une commande dans un sous-processus sans attendre sa fin (comme un thread)
for
est ici pour analyser toutes les 255 adresses IP. Il utilise la commande seq
pour répertorier tous les nombres.wait
: après avoir lancé nos demandes, nous voulons voir s'il y a des réponses. Pour ce faire, nous venons de mettre wait
après la boucle .wait
ressemble à la fonction join()
dans d'autres langues.()
: les parenthèses sont ici pour interpréter toutes les sorties sous forme de texte afin que nous puissions les donner à grep
grep
: nous voulons seulement voir les réponses. le second grep est juste ici pour mettre en évidence les IP.hth
La mauvaise partie de ma solution est d’imprimer tous les résultats à la fin. C'est parce que grep a un assez grand tampon pour insérer des lignes dans . La solution consiste à ajouter --line-buffered
au premier grep . Comme ceci:
(for n in $(seq 1 254);do Sudo arping -c1 10.0.0.$n & done ; wait) | grep --line-buffered reply | grep --color -E '([0-9]+\.){3}[0-9]+'
Bien qu’une vieille question, elle semble toujours être importante (au moins assez pour que je puisse y faire face). Mon script s'appuie également sur nmap, donc rien de spécial ici si ce n'est que vous pouvez définir l'interface que vous souhaitez analyser et que la plage d'adresses IP est créée automatiquement (du moins en quelque sorte).
C'est ce que je suis venu avec
#!/bin/bash
#Script for scanning the (local) network for other computers
command -v nmap >/dev/null 2>&1 || { echo "I require nmap but it's not installed. Aborting." >&2; exit 1; }
if [ -n ""$@"" ]; then
ip=$(/sbin/ifconfig $1 | grep 'inet ' | awk '{ print $2}' | cut -d"." -f1,2,3 )
nmap -sP $ip.1-255
else
echo -e "\nThis is a script for scanning the (local) network for other computers.\n"
echo "Enter Interface as parameter like this:"
echo -e "\t./scannetwork.sh $(ifconfig -lu | awk '{print $2}')\n"
echo "Possible interfaces which are up are: "
for i in $(ifconfig -lu)
do
echo -e "\033[32m \t $i \033[39;49m"
done
echo "Interfaces which could be used but are down at the moment: "
for i in $(ifconfig -ld)
do
echo -e "\033[31m \t $i \033[39;49m"
done
echo
fi
Une remarque: ce script est créé sur OSX, il est donc possible que des modifications soient apportées aux environnements Linux.
#!/bin/bash
#Get the ip address for the range
ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}' | cut -d"." -f1,2,3)
# ping test and list the hosts and echo the info
for range in $ip ; do [ $? -eq 0 ] && ping -c 1 -w 1 $range > /dev/null 2> /dev/null && echo "Node $range is up"
done
Si vous souhaitez fournir une liste d'hôtes, vous pouvez le faire avec nmap, grep et awk.
Installez nmap:
$ Sudo apt-get install nmap
Créez le fichier hostcheck.sh comme ceci:
hostcheck.sh
#!/bin/bash
nmap -sP -iL hostlist -oG pingscan > /dev/null
grep Up pingscan | awk '{print $2}' > uplist
grep Down pingscan | awk '{print $2}' > downlist
-sP: Ping Scan - pas plus que de déterminer si l'hôte est en ligne
-iL: entrée de la liste des hôtes/réseaux
-oG: les résultats de l'analyse de sortie au format Grepable, au nom de fichier donné.
/ dev/null: ignore la sortie
Changer l'autorisation d'accès:
$ chmod 775 hostcheck.sh
Créer un fichier liste d’hôtes avec la liste des hôtes à vérifier (nom d’hôte ou IP):
liste d'hôtes (exemple)
192.168.1.1-5
192.168.1.101
192.168.1.123
192.168.1.1-5 est une plage d'adresses IP
Exécutez le script:
./hostcheck.sh hostfile
Sera généré des fichiers pingscan avec toutes les informations, uplist avec les hôtes en ligne (Up) et downlist avec les hôtes hors ligne (Down).
uplist (exemple)
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.101
liste déroulante (exemple)
192.168.1.5
192.168.1.123
Le code (diabolique) suivant s'exécute plus de deux fois plus vite que la méthode nmap
for i in {1..254} ;do (ping 192.168.1.$i -c 1 -w 5 >/dev/null && echo "192.168.1.$i" &) ;done
prend environ 10 secondes, où le nmap standard
nmap -sP 192.168.1.1-254
prend 25 secondes ...
Eh bien, cela fait partie de mon script.
ship.sh ???? Un adressage réseau simple et pratique ???? multitool avec beaucoup de fonctionnalités ????
Réseau Pings, affiche les hôtes en ligne de ce réseau avec leurs adresses IP et MAC locales
Il ne nécessite aucune édition. Nécessite l'autorisation root pour s'exécuter.
GOOGLE_DNS="8.8.8.8"
ONLINE_INTERFACE=$(ip route get "${GOOGLE_DNS}" | awk -F 'dev ' 'NR == 1 {split($2, a, " "); print a[1]}')
NETWORK_IP=$(ip route | awk "/${ONLINE_INTERFACE}/ && /src/ {print \$1}" | cut --fields=1 --delimiter="/")
NETWORK_IP_CIDR=$(ip route | awk "/${ONLINE_INTERFACE}/ && /src/ {print \$1}")
FILTERED_IP=$(echo "${NETWORK_IP}" | awk 'BEGIN{FS=OFS="."} NF--')
ip -statistics neighbour flush all &>/dev/null
echo -ne "Pinging ${NETWORK_IP_CIDR}, please wait ..."
for Host in {1..254}; do
ping "${FILTERED_IP}.${Host}" -c 1 -w 10 &>/dev/null &
done
for JOB in $(jobs -p); do wait "${JOB}"; done
ip neighbour | \
awk 'tolower($0) ~ /reachable|stale|delay|probe/{printf ("%5s\t%s\n", $1, $5)}' | \
sort --version-sort --unique
#!/bin/bash
for ((n=0 ; n < 30 ; n+=1))
do
ip=10.1.1.$n
if ping -c 1 -w 1 $ip > /dev/null 2> /dev/null >> /etc/logping.txt; then
echo "${ip} is up" # output up
# sintax >> /etc/logping.txt log with .txt format
else
echo "${ip} is down" # output down
fi
done