¿Cómo puedo escribir un script de linux bash que me diga qué equipos están encendidos en mi LAN?


¿Cómo puedo escribir un script de linux bash que me diga qué computadoras están encendidas en mi LAN ?

Ayudaría si pudiera darle como entrada un rango de IP.

Author: Dumb Questioner, 2009-04-09

16 answers

Sugeriría usar la bandera 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

Dicho esto, si quieres escribirlo tú mismo (lo cual es bastante justo), así es como lo haría:{[33]]}

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

Puede usar la sintaxis {1..10} 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} - que hace dir1 y dir2, cada uno conteniendo sub1 y sub2)

Entonces, para generar una lista de IPS, haríamos algo como

$ echo 192.168.1.{1..10}
192.168.1.1 192.168.1.2 [...] 192.168.1.10

Bucles

Para hacer un bucle sobre algo en bash, se usa for:

$ for thingy in 1 2 3; do echo $thingy; done
1
2
3

Ping

Siguiente, a ping.. El comando ping varía un poco con diferentes sistemas operativos, diferentes distribuciones/versiones (actualmente estoy usando OS X)

De forma predeterminada (de nuevo, en la versión OS X de ping) hará ping hasta que se interrumpa, lo que no va a funcionar para esto, por lo que ping -c 1 solo intentará enviar un paquete, que debería ser suficiente para determinar si una máquina está activa.

Otro problema es el valor de tiempo de espera, que parece ser de 11 segundos en esta versión de ping.. Se cambia usando la bandera -t. Un segundo debería ser suficiente para ver si una máquina en la red local está viva 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, así que podemos hacerlo..

Ping-c 1-t 1 192.168.1.1 && echo "192.168.1.1 is up!"

La otra forma sería usar el código de salida de ping.. El comando ping saldrá con exit-code 0 (success) si funcionó, y un código distinto de cero si falló. En bash se obtiene el código de salida de los últimos comandos con la variable $?

Entonces, para comprobar si el comando funcionó, lo 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

Escondiéndose salida de ping

Por último, no necesitamos ver la salida de ping, por lo que podemos redirigir stdout a /dev/null con la 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 los ping: sendto: Host is down mensajes), se 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, utilizando 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 toma aproximadamente 1 segundo (ya que establezca el indicador de tiempo de espera-t en 1 segundo). Solo puede ejecutar un comando ping a la vez.. La forma obvia de evitar esto es usar hilos, para que pueda ejecutar comandos concurrentes, pero eso está más allá de lo que debe usar bash para..

"Subprocesos de Python-un primer ejemplo" explica cómo usar el módulo de subprocesos de Python para escribir un ping'er multi-threaded.. Aunque en ese punto, una vez más sugeriría usar nmap -sn..

 75
Author: dbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 18:29:07

En el mundo real, se podría utilizar 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 quieres hacer esto como un ejercicio de bash, puedes ejecutar ping para cada dirección y analizar la salida, pero eso es otra historia.

 14
Author: Tiberiu Ana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-05 10:33:18

Suponiendo que mi red es 10.10.0.0 / 24, si corro un ping en la dirección de difusión como

ping -b 10.10.0.255

Obtendré una respuesta de todos los equipos de esta red que no bloquearon su puerto 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 

Así que solo tienes que extraer la 4a 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á duplicado, y es posible que deba eliminar el ':'.

EDITAR desde comentarios : la opción-c limita el número de pings dado que el script terminará, también podemos limitarnos a nosotros mismos en IPs únicas

ping -c 5 -b 10.10.0.255 | grep 'bytes from' | awk '{ print $4 }' | sort | uniq
 10
Author: chburd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 12:32:22

También Hay fping:

fping -g 192.168.1.0/24

O:

fping -g 192.168.1.0 192.168.1.255

O mostrar solo los anfitriones que están vivos:

fping -ag 192.168.1.0/24

Pings hosts en paralelo por lo que el análisis es muy rápido. No conozco una distribución que incluya fping en su instalación por defecto, pero en la mayoría de las distribuciones se puede obtener a través del gestor de paquetes.

 8
Author: d0k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 19:18:05

También usando el método "ping the broadcast address" señalado por chburd, esta tubería debería hacer el truco para usted:

ping -c 5 -b 10.11.255.255 | sed -n 's/.* \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p' | sort | uniq

Por supuesto, usted tendría que cambiar la dirección de difusión a la de su red.

 2
Author: Can Berk Güder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 09:32:49

Solo por diversión, aquí hay una alternativa

     #!/bin/bash
     nmap -sP 192.168.1.0/24 > /dev/null 2>&1 && arp -an | grep -v incomplete | awk '{print$2}' | sed -e s,\(,, | sed -e s,\),,

 2
Author: Eddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 18:44:05

Si te limitas a tener solo el último octeto cambiando, este script debería hacerlo. Debería ser bastante obvio cómo extenderlo de uno a varios octetos.

#! /bin/bash
BASE=$1
START=$2
END=$3

counter=$START

while [ $counter -le $END ]
do
  ip=$BASE.$counter
  if ping -qc 2 $ip
  then
    echo "$ip responds"
  fi
  counter=$(( $counter + 1 ))
done
 1
Author: Vatine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 09:15:32
 1
Author: raspi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 18:57:51

Como señalaron otros posters, nmap es el camino a seguir, pero aquí está cómo hacer el equivalente de un escaneo ping en bash. Yo no usaría el ping broadcast, ya que muchos sistemas están configurados para no responder a broadcast ICMP hoy en día.

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
Author: Don Werve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-09 19:09:30
#!/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
Author: hemanth.hm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-17 05:51:56

Aunque es una vieja pregunta, todavía parece ser importante (al menos lo suficientemente importante para mí para lidiar con esto). Mi script también se basa en nmap, por lo que nada especial aquí, excepto que puede definir qué interfaz desea escanear y el rango de IP se crea automáticamente (al menos un poco).

Esto es lo que se me ocurrió

#!/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

Una observación: Este script se crea en OSX, por lo que puede haber algunos cambios en los entornos linux.

 1
Author: d3v3l,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-19 14:12:32

Si desea proporcionar una lista de hosts, puede hacerlo con nmap, grep y awk.

Instalar nmap:

$ sudo apt-get install nmap

Crear archivo hostcheck.sh así:

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-no vaya más allá de determinar si el host está en línea

- iL: Entrada de la lista de hosts/redes

-oG : Los resultados del análisis de salida en formato Grepable, al nombre de archivo dado.

/dev / null : Descarta la salida

Cambiar el acceso permiso:

$ chmod 775 hostcheck.sh

Crear archivo hostlist con la lista de hosts a comprobar (nombre de host o IP):

Hostlist (Ejemplo)

192.168.1.1-5
192.168.1.101
192.168.1.123

192.168.1.1-5 es un rango de IPs

Ejecute el script:

./hostcheck.sh hostfile

Se generarán archivos pingscan con toda la información, uplist con los hosts online (Up) y downlist con los hosts offline (Down).

Uplist (Ejemplo)

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.101

Lista descendente (Ejemplo)

192.168.1.5
192.168.1.123
 1
Author: viniciusfcosta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-14 16:44:25

Algunas máquinas no responden pings (por ejemplo, firewalls).

Si solo desea la red local, puede usar este comando:

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

Explicaciones parte !

  1. arping es un comando que envía peticiones ARP. Está presente en la mayoría de linux.

Ejemplo:

sudo arping -c1 10.0.0.14

El sudo no es necesario si eres root ofc.

  • 10.0.0.14: la ip que desea probar
  • -c1: enviar solo uno solicitud.

  1. &: el carácter' no quiero esperar '

Este es un personaje realmente útil que te da la posibilidad de lanzar un comando en un subproceso sin esperar a que termine (como un hilo)


  1. el bucle for está aquí para arping todas las 255 direcciones ip. Utiliza el comando seq para listar todos los números.

  1. wait: después de lanzar nuestras solicitudes queremos ver si hay algunas respuestas. A hacerlo así que solo ponemos wait después del bucle. wait se parece a la función join() en otros idiomas.

  1. (): los paréntesis están aquí para interpretar todas las salidas como texto para que podamos dárselas a {[14]]}

  1. grep: solo queremos ver respuestas. el segundo grep está aquí para resaltar IPs.

Hth

Editar 20150417: Maxi Actualización !

La parte mala de mi solución es que imprime todos los resultados al final. Es porque grep tiene un búfer lo suficientemente grande como para poner algunas líneas dentro. la solución es añadir --line-buffered al primer grep. así:

(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
Author: Boop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-17 13:15:45
#!/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
Author: erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-28 07:24:56

El siguiente código (malvado) se ejecuta más del DOBLE de rápido que el método nmap

for i in {1..254} ;do (ping 192.168.1.$i -c 1 -w 5  >/dev/null && echo "192.168.1.$i" &) ;done

Toma alrededor de 10 segundos, donde el nmap estándar

nmap -sP 192.168.1.1-254

Toma 25 segundos...

 0
Author: Mike Redrobe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-16 17:12:32

Bueno, esto es parte de un guión mío.

Ship.sh Una sencilla y práctica multiherramienta de direccionamiento de red con muchas características

Red Pings, muestra los hosts en línea en esa red con su dirección IP y MAC local

No requiere ninguna edición. Necesita permiso de root para ejecutarse.

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
Author: xtonousou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-13 19:39:45