Sugeriría usar el indicador de escaneo de ping 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
Dicho esto, si quieres escribirlo tú mismo (lo cual es bastante justo), así es como lo haría:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
..y una explicación de cada bit del comando anterior:
Generando lista de direcciones IP
Puedes usar el {1..10}
sintaxis para generar una lista de números, por ejemplo..
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
(también es útil para cosas como mkdir {dir1,dir2}/{sub1,sub2}
- lo que hace dir1
y dir2
, cada uno conteniendo sub1
y sub2
)
Entonces, para generar una lista de direcciones IP, haríamos algo como
$ echo 192.168.1.{1..10}
192.168.1.1 192.168.1.2 [...] 192.168.1.10
Bucles
Para recorrer algo en bash, usa for
:
$ for thingy in 1 2 3; do echo $thingy; done
1
2
3
Hacer ping
A continuación, para hacer ping... El comando ping varía un poco con diferentes sistemas operativos, diferentes distribuciones/versiones (estoy usando OS X actualmente)
De forma predeterminada (nuevamente, en la versión OS X de ping
) hará ping hasta que se interrumpa, lo que no funcionará para esto, así que ping -c 1
solo intentará enviar un paquete, que debería ser suficiente para determinar si una máquina está funcionando.
Otro problema es el valor del tiempo de espera, que parece ser de 11 segundos en esta versión de ping. Se cambia usando el -t
bandera. Un segundo debería ser suficiente para ver si una máquina en la red local está activa o no.
Entonces, el comando ping que usaremos es...
$ 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
Comprobando el resultado del ping
A continuación, necesitamos saber si la máquina respondió o no.
Podemos usar el &&
operador para ejecutar un comando si el primero tiene éxito, por ejemplo:
$ echo && echo "It works"
It works
$ nonexistantcommand && echo "This should not echo"
-bash: nonexistantcommand: command not found
Bien, entonces podemos hacer...
ping -c 1 -t 1 192.168.1.1 &&echo "¡192.168.1.1 está activo!"
La otra forma sería usar el código de salida de ping. El comando ping saldrá con el código de salida 0 (éxito) si funcionó, y un código distinto de cero si falló. En bash obtienes el código de salida de los últimos comandos con la variable $?
Entonces, para verificar si el comando funcionó, haríamos...
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
Ocultar salida de ping
Lo último, no necesitamos ver el resultado del ping, por lo que podemos redirigir stdout
a /dev/null
con el >
redirección, por ejemplo:
$ ping -c 1 -t 1 192.168.1.1 > /dev/null && echo "IP is up"
IP is up
Y para redirigir stderr
(para descartar el ping: sendto: Host is down
mensajes), utiliza 2>
- por ejemplo:
$ errorcausingcommand
-bash: errorcausingcommand: command not found
$ errorcausingcommand 2> /dev/null
$
El guión
Entonces, para combinar todo eso..
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
O, usando el &&
método, en una sola línea:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
Problema
Es lento.. Cada comando ping tarda aproximadamente 1 segundo (ya que configuramos el indicador -t timeout en 1 segundo). Solo puede ejecutar un comando ping a la vez. La forma obvia de evitar esto es usar subprocesos, por lo que puede ejecutar comandos concurrentes, pero eso va más allá de lo que debería usar bash.
"Subprocesos de Python:un primer ejemplo" explica cómo usar el módulo de subprocesos de Python para escribir un ping'er de subprocesos múltiples. Aunque en ese punto, sugeriría una vez más usar nmap -sn
..
En el mundo real, podría usar nmap para conseguir lo que quieres.
nmap -sn 10.1.1.1-255
Esto hará ping a todas las direcciones en el rango 10.1.1.1 a 10.1.1.255 y le permitirá saber cuáles responden.
Por supuesto, si de hecho quiere hacer esto como un ejercicio bash, puede ejecutar ping para cada dirección y analizar la salida, pero esa es otra historia.
Suponiendo que mi red es 10.10.0.0/24, si ejecuto un ping en la dirección de transmisión como
ping -b 10.10.0.255
Obtendré una respuesta de todas las computadoras en esta red que no bloquearon su puerto 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
Entonces solo tienes que extraer la cuarta columna, con awk por ejemplo:
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:
Bueno, obtendrá un duplicado y es posible que deba eliminar el ':'.
EDITAR desde comentarios:la opción -c limita el número de pings ya que el script finalizará, también podemos limitarnos a IP únicas
ping -c 5 -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }' | sort | uniq