web-dev-qa-db-fra.com

Comment puis-je écrire un script linux bash qui me dit quels ordinateurs sont allumés sur mon réseau local?

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.

32
Dumb Questioner

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:

Génération de liste d'adresses IP

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

Boucles

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

Ping

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

Vérification du résultat du ping

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

Masquer la sortie ping

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
$

Le scénario

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

Problème

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 ..

77
dbr

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.

14
Tiberiu Ana

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
10
chburd

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.

8
d0k

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.

2
Can Berk Güder

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 
1
Vatine

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
1
Don Werve

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]+'

Partie explications!

  1. 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.

  1. &: 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)


  1. la boucle for est ici pour analyser toutes les 255 adresses IP. Il utilise la commande seq pour répertorier tous les nombres.

  1. 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.

  1. (): les parenthèses sont ici pour interpréter toutes les sorties sous forme de texte afin que nous puissions les donner à grep

  1. grep: nous voulons seulement voir les réponses. le second grep est juste ici pour mettre en évidence les IP.

hth

Modifier 20150417: Maxi Update!

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]+'
1
Boop

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.

1
d3v3l
#!/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
1
hemanth.hm

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
1
viniciusfcosta
1
raspi

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 ...

0
Mike Redrobe

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
0
xtonousou
#!/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
0
erik