Как я могу написать сценарий linux bash, который говорит мне, какие компьютеры включены в моей локальной сети?
Как я могу написать сценарий Linux bash, который говорит мне, какие компьютеры включены в моей локальной сети ?
это помогло бы, если бы я мог дать ему в качестве входного диапазона IP.
16 ответов
я бы предложил использовать флаг пинг-сканирования 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
тем не менее, если вы хотите написать это сами (что достаточно справедливо), вот как я бы это сделал:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
..и объяснение каждого бита приведенной выше команды:
создание списка IP-адресов
вы можете использовать {1..10}
синтаксис для создания списка чисел, например..
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
(это также полезно для таких вещей, как mkdir {dir1,dir2}/{sub1,sub2}
- что делает dir1
и dir2
, содержащих sub1
и sub2
)
Итак, чтобы создать список IP-адресов, мы сделаем что-то вроде
$ echo 192.168.1.{1..10}
192.168.1.1 192.168.1.2 [...] 192.168.1.10
петли
чтобы зациклиться на чем-то в bash, вы используете for
:
$ for thingy in 1 2 3; do echo $thingy; done
1
2
3
пинг
далее, чтобы пинг.. Команда ping немного отличается от разных операционных систем, разных дистрибутивов / версий (в настоящее время я использую OS X)
по умолчанию (опять же, в версии OS X из ping
) он будет пинговать, пока не прервется, что не будет работать для этого, так что ping -c 1
будет пытаться отправить только один пакет, которого должно быть достаточно, чтобы определить, работает ли машина.
еще одна проблема-значение тайм-аута, которое, кажется, составляет 11 секунд в этой версии ping.. Он изменен с помощью -t
флаг. Одной секунды должно быть достаточно, чтобы увидеть, жива ли машина в локальной сети или нет.
Итак, команда ping мы будем использовать есть..
$ 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
проверка результата пинга
Далее, нам нужно знать, ответила ли машина или нет..
мы можем использовать &&
оператор для выполнения команды, если первая успешно, например:
$ echo && echo "It works"
It works
$ nonexistantcommand && echo "This should not echo"
-bash: nonexistantcommand: command not found
хорошая, так что мы можем сделать..
ping-c 1-t 1 192.168.1.1 && echo "192.168.1.1 вверх!"
другой способ-использовать код выхода из ping.. Команда ping выйдет с кодом exit-code 0 (success), если она работал, и ненулевой код, если он не. В bash вы получаете последние команды выхода кода с переменной $?
Итак, чтобы проверить, работает ли команда, мы сделаем это..
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
скрытие вывода ping
последнее, нам не нужно видеть вывод ping, поэтому мы можем перенаправить stdout
to /dev/null
С >
редирект, например:
$ ping -c 1 -t 1 192.168.1.1 > /dev/null && echo "IP is up"
IP is up
и направить stderr
(отбросить ping: sendto: Host is down
сообщения), вы используете 2>
- для пример:
$ errorcausingcommand
-bash: errorcausingcommand: command not found
$ errorcausingcommand 2> /dev/null
$
скрипт
Итак, чтобы объединить все это..
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
или, используя &&
метод, в одной строке:
for ip in 192.168.1.{1..10}; do ping -c 1 -t 1 $ip > /dev/null && echo "${ip} is up"; done
это медленно.. Каждая команда ping занимает около 1 секунды (так как мы устанавливаем флаг-t timeout в 1 секунду). Он может запускать только одну команду ping за раз.. Очевидный способ обойти это-использовать потоки, поэтому вы можете запускать параллельные команды, но это выходит за рамки того, что вы должны использовать bash для..
"Python threads - первый пример" объясняет, как использовать модуль Python threading для записи многопоточного ping'ER.. Хотя в этот момент я бы еще раз предложил использовать nmap -sn
..
в реальном мире вы можете использовать в Nmap чтобы получить то, что вы хотите.
nmap -sn 10.1.1.1-255
это будет пинговать все адреса в диапазоне от 10.1.1.1 до 10.1.1.255 и даст вам знать, какие из них отвечают.
конечно, если вы действительно хотите сделать это как упражнение bash, вы можете запустить ping для каждого адреса и проанализировать вывод, но это совсем другая история.
предполагая, что моя сеть 10.10.0.0/24, Если я запускаю пинг на широковещательный адрес как
ping -b 10.10.0.255
я получу ответ от всех компьютеров в этой сети, которые не заблокировали их порт ICMP ping.
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
поэтому вам просто нужно извлечь 4-й столбец, например, с awk:
ping -b 10.10.0.255 | grep 'bytes from' | awk '{ print }'
10.10.0.12:
10.10.0.6:
10.10.0.71:
10.10.0.95:
Ну, вы получите дубликат, и вам может потребоваться удалить':'.
редактировать комментарии : опция-c ограничивает количество запросов поскольку сценарий закончится, мы также можем ограничить себя уникальными IPs
ping -c 5 -b 10.10.0.255 | grep 'bytes from' | awk '{ print }' | sort | uniq
появилась fping:
fping -g 192.168.1.0/24
или:
fping -g 192.168.1.0 192.168.1.255
или показывать только живые хосты:
fping -ag 192.168.1.0/24
он пингует хосты параллельно, поэтому сканирование происходит очень быстро. Я не знаю дистрибутива, который включает fping
в его установке по умолчанию, но в большинстве дистрибутивов вы можете получить его через Диспетчер пакетов.
также используя метод "ping the broadcast address", указанный chburd, эта труба должна сделать трюк для вас:
ping -c 5 -b 10.11.255.255 | sed -n 's/.* \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*//p' | sort | uniq
конечно, вам придется изменить широковещательный адрес на адрес вашей сети.
просто для удовольствия, вот альтернативный
#!/bin/bash nmap -sP 192.168.1.0/24 > /dev/null 2>&1 && arp -an | grep -v incomplete | awk '{print}' | sed -e s,\(,, | sed -e s,\),,
Если вы ограничиваете себя только изменением последнего октета, этот скрипт должен это сделать. Должно быть довольно очевидно, как расширить его от одного до нескольких октетов.
#! /bin/bash BASE= START= END= counter=$START while [ $counter -le $END ] do ip=$BASE.$counter if ping -qc 2 $ip then echo "$ip responds" fi counter=$(( $counter + 1 )) done
как указывали другие плакаты,nmap
это путь, но вот как сделать эквивалент сканирования ping в bash. Я бы не использовал широковещательный пинг, так как в настоящее время многие системы настроены не реагировать на широковещательный ICMP.
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
#!/bin/bash
#Get the ip address for the range
ip=$(/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print }' | 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
хотя это старый вопрос, он все еще кажется важным (по крайней мере, достаточно важным для меня, чтобы справиться с этим). Мой скрипт также полагается на nmap, поэтому здесь нет ничего особенного, кроме того, что ou может определить, какой интерфейс вы хотите сканировать, и диапазон IP создается автоматически (по крайней мере, вид).
вот что я придумал
#!/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 | grep 'inet ' | awk '{ print }' | 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 }')\n"
echo "Possible interfaces which are up are: "
for i in $(ifconfig -lu)
do
echo -e "3[32m \t $i 3[39;49m"
done
echo "Interfaces which could be used but are down at the moment: "
for i in $(ifconfig -ld)
do
echo -e "3[31m \t $i 3[39;49m"
done
echo
fi
одно замечание: этот скрипт создан на OSX, поэтому могут быть некоторые изменения в средах linux.
если вы хотите предоставить список хостов, это можно сделать с помощью nmap, grep и awk.
установить nmap:
$ sudo apt-get install nmap
создать файл hostcheck.sh вот так:
hostcheck.sh
#!/bin/bash
nmap -sP -iL hostlist -oG pingscan > /dev/null
grep Up pingscan | awk '{print }' > uplist
grep Down pingscan | awk '{print }' > downlist
- sP: Ping Scan-не идти дальше, чем определение, если хост находится в сети
- iL: вход из списка хостов / сетей
- oG: вывод результатов сканирования в формате Grepable в заданное имя файла.
/dev / null: отбрасывает вывод
изменить разрешение доступа:
$ chmod 775 hostcheck.sh
создать файл hostlist со списком хостов для проверки (имя хоста или IP):
hostlist (пример)
192.168.1.1-5
192.168.1.101
192.168.1.123
192.168.1.1-5-это диапазон IPs
выполнить скрипт:
./hostcheck.sh hostfile
будут сгенерированы файлы pingscan со всей информацией, uplist с хостами онлайн (вверх) и downlist с хостами в автономном режиме (Вниз.)
uplist (пример)
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.101
downlist (пример)
192.168.1.5
192.168.1.123
некоторые машины не отвечают на пинги (например, межсетевые экраны).
если вы хотите только локальную сеть, вы можете использовать эту команду:
(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
- это команда, которая отправляет запросы ARP. Он присутствует на большинстве linux.
пример:
sudo arping -c1 10.0.0.14
sudo не является необходимым, если вы корень ofc.
-
10.0.0.14
: ip, который вы хотите тест -
-c1
: отправить всего один запрос.
-
&
: символ "я-не-хочу-ждать"
это действительно полезный символ, который дает вам возможность запускать команду в подпроцессе, не дожидаясь его завершения (например, поток)
- the
for
loop здесь для arping всех 255 ip-адресов. Он используетseq
команда для перечисления всех числа.
-
wait
: после того, как мы запустили наши запросы, мы хотим посмотреть, есть ли ответы. Для этого мы просто ставимwait
после цикла.wait
похоже на функциюjoin()
в других языках.
-
()
: скобки здесь, чтобы интерпретировать все выходы как текст, чтобы мы могли дать егоgrep
-
grep
: мы хотим видеть ответы. второй grep просто здесь, чтобы выделить IPs.
hth
Edit 20150417: Обновление Maxi !
плохая часть моего решения заключается в том, что он печатает все результаты в конце. Это потому, что у grep есть достаточно большой буфер, чтобы поместить некоторые строки внутрь.
решение состоит в том, чтобы добавить --line-buffered
к первому grep.
вот так:
(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]+'
#!/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
следующий (злой) код выполняется более чем в два раза быстрее, чем метод nmap
for i in {1..254} ;do (ping 192.168.1.$i -c 1 -w 5 >/dev/null && echo "192.168.1.$i" &) ;done
занимает около 10 секунд, где стандартный nmap
nmap -sP 192.168.1.1-254
занимает 25 секунд...
Ну, это часть моего сценария.
ship.sh простой, удобный сетевой адресации мультитул с большим количеством функций
pings network, отображает онлайн-хосты в этой сети с их локальным IP и MAC-адресом
это не требует редактирования. Требуется разрешение root для запуска.
GOOGLE_DNS="8.8.8.8"
ONLINE_INTERFACE=$(ip route get "${GOOGLE_DNS}" | awk -F 'dev ' 'NR == 1 {split(, 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() ~ /reachable|stale|delay|probe/{printf ("%5s\t%s\n", , )}' | \
sort --version-sort --unique