PDA

Просмотр полной версии : Скрипт на баше


TNT
22.05.2011, 15:34
Нужно написать скрипт на bash/ksh. Нужно вывести все системы, имеющие IP адрес в подсетях исходной системы и отвечающие на ARP запросы, потом вывести информацию об использовании дискового пространства локальных файловых систем.

Т.к. я хреново это все знаю, то намутил кучу и уже запутался.
Просьба не обращать внимания на кучу лишних переменных, знаю, что убрать можно много.


#! /usr/bin/ksh

#подсчет количества подсетей
netcount=`ifconfig -a | sed -n $q"p" | awk '{if($5=="broadcast") print $2}' | wc -l`


i=1

while [ $i -le $netcount ]
do

#выборка маски
ifconfig -a | awk '{if($5=="broadcast") print $4}' | tr '[a-f]' '[A-F]' | read a
echo "ibase=16;$a"|bc | read mask

#выборка адреса подсети
ifconfig -a | awk '{if($5=="broadcast") print $2}' | read NET
net=`echo $NET`
n1=`echo $net | awk -F"." '{print $1}'`
n2=`echo $net | awk -F"." '{print $2}'`
n3=`echo $net | awk -F"." '{print $3}'`
n4=`echo $net | awk -F"." '{print $4}'`
net=`expr $n1 \* 16777216 + $n2 \* 65536 + $n3 \* 256 + $n4`

#расчет последнего адреса в сети, то же самое, что 2^32-1
max=`expr 255 \* 16777216 + 255 \* 65536 + 255 \* 256 + 255`

#расчет количества хостов
host=`expr $max - $mask`


#подсчет первого адреса в подсети: адрес бродкаста минус количество хостов
ifconfig -a | sed -n $q"p" | awk '{if($5=="broadcast") print $6}' | read startip

n1=`echo $startip | awk -F"." '{print $1}'`
n2=`echo $startip | awk -F"." '{print $2}'`
n3=`echo $startip | awk -F"." '{print $3}'`
n4=`echo $startip | awk -F"." '{print $4}'`

startip=`expr $n1 \* 16777216 + $n2 \* 65536 + $n3 \* 256 + $n4`

start=`expr $startip - $host`


end=`expr $net + $host - 1`


j=$start
while [ $j -le $end ]
do
a1=`expr $j / 16777216`
r=`expr $j % 16777216`
a2=`expr $r / 65536`
r=`expr $r % 65536`
a3=`expr $r / 256`
a4=`expr $r % 256`

#обновление ARP таблицы
echo "ping $a1.$a2.$a3.$a4 ..."

arp $a1.$a2.$a3.$a4 >>log
if [ $? -eq 0 ]
then
echo "Disk space of local filesystems on $a1.$a2.$a3.$a4:"
rsh $j df -l
fi
j=`expr $j + 1`
done
i=`expr $i + 1`
done



Вот перебор по подсетям я и не вкупаю как сделать. Моя куча-мала три раза перебирает первую подсеть и все.
100 пудов это все пишется, конечно, гораздо короче и менее запутано. Если кто подскажет - буду очень признательный.

VK
22.05.2011, 15:42
у тебя в первой же строчке ошибка, если в системе два адреса из одной сети - он тебе выдаст не одну сеть, а две. если пять - то пять.
с остальным не разбирался, запутано у тебя все.

TNT
22.05.2011, 15:50
Запутано - не то слово...
Скрипт знакомый писал, потом я его еще мучал.

В первой строчке ключ -l не дописал к wc. Вообще, выводит правильно - на три подсети три записи.

VK
22.05.2011, 15:52
а на три сети, но пять адресов?

TNT
22.05.2011, 16:00
Я так понимаю, вот эта строчка имеется в виду:

ifconfig -a | awk '{if($5=="broadcast") print $2}' | wc -l

Так после awk же остаются только бродкаст-адреса, т.е. их в любом случае столько же, сколько подсетей.
Три я написал потому, что там, где скрипт исполняется их три, а адресов то там прилично.

VK
22.05.2011, 16:04
$ ifconfig -a | awk '{if($5=="broadcast") print $2}'
192.168.10.250
192.168.11.250
192.168.10.111
192.168.11.111
85.114.xxx.xxx

вывело пять, хотя сетей всего три.
при этом есть еще два tun интерфейса от openvpn, в которых отсутствует broadcast и соответственно скрипт о них ничего не узнает :)

VK
22.05.2011, 16:08
в общем, эту строчку, изначально кривую, надо заменить вот этим - ifconfig -a | grep broadcast |sort -u +5 |wc -l
у меня на freebsd работает правильно.

TNT
22.05.2011, 16:11
Благодарю :) Я хреново в этом разбираюсь :)
То есть бродкаст-адресов может быть больше, чем сетей? Я думал, что для каждой сети может быть только по одному бродкасту: адрес сети с маской.

VK
22.05.2011, 16:15
броадкаст выводится на каждый адрес, вне зависимости от того, есть ли еще адреса из этой сети в системе или нет.
а вообще завязываться на ifocnfig опасно, так как его вывод не стандартизирован и то, что у меня работает правильно на фре, может не сработать на линухе... правда как сделать по-другому пока не знаю :)

TNT
22.05.2011, 16:23
Мне надо, чтобы на Солярисе работало :) В общем-то, должно.

На ifconfig завязываться нужно - попросили именно так делать. А вообще, по идее, можно еще из hosts вытащить. Но сказано не делать. Хотя, если есть третий способ без hosts, думаю, должно прокатить.

VK
22.05.2011, 16:29
я это к тому сказал, что на твоем солярисе ifconfig может иметь иной вывод и соответственно скрипт будет работать неверно.

TNT
22.05.2011, 16:30
Да, я понял. Но в нем проблем нет - все правильно выводится.

Вождь
22.05.2011, 17:49
можно вместо ifconfig юзать ip a, оно вроде более стандартизировано

VK
22.05.2011, 17:56
$ ip a
-bash: ip: command not found

TNT
22.05.2011, 17:58
$ ip a
ksh: ip: not found
:)

Потихоньку начал раскуривать, решил все заново писать.

ΛLIEN
22.05.2011, 20:26
Ну так во фряхе или соляре iproute2 нет. Откуда ip тогда взяться.

VK
22.05.2011, 21:13
это была демонстрация несостоятельности заявления, что "ip a более стандартизировано".

Вождь
22.05.2011, 22:29
это бало не заявление а предположение

TNT
22.05.2011, 23:47
Переписал в итоге все, вроде работает. Если проканает - напишу, как сделать, вдруг кому надо.

ΛLIEN
23.05.2011, 01:36
Переписал в итоге все, вроде работает. Если проканает - напишу, как сделать, вдруг кому надо.
Сомневаюсь, что без напильника это заработает под линухом, как раз из-за нестандартного вывода ifconfig.

VK
23.05.2011, 01:49
Сомневаюсь, что без напильника это заработает под линухом, как раз из-за нестандартного вывода ifconfig.
в том-то и дело, что стандартов на это нет.
но дело даже не в этом, вряд ли это кому-то может понадобиться еще :) это плод больного воображения препода и только. к жизни отношения не имеющий.

TNT
24.05.2011, 21:03
это плод больного воображения препода и только. к жизни отношения не имеющий.
Именно так. Слабо понимаю, нахрен это надо.

FeD
24.05.2011, 21:22
Слабо понимаю, нахрен это надо.

а зачем в школе на бэйсике пишут проги для решения квадратных уравнений? это тоже бред больного воображения? ведь можно ж в калькуляторе посчитать

TNT
24.05.2011, 22:33
Плохой пример, это разные вещи.

TNT
25.05.2011, 15:04
В общем, сделал все заново так (вдруг кому интересно):


#!/bin/bash
# Additional functions
# Decimal to binary
binary=0
decToBin(){
binary=`echo $1 | gawk -F. '{OFMT = "%.10g"; print $1*2^24+$2*2^16+$3*2^8+$4}'`
}

#Binary to decimal
decimal=0.0.0.0
binToDec(){
decimal=`echo $1 | gawk '{
temp = $1;
for (i = 1; i<=4; i++){
IP[i] = temp%2^8;
temp = int(temp/2^8);
}
print IP[4]"."IP[3]"."IP[2]"."IP[1]
}'`
}

# Part A Getting list of subnets and their masks.
subnets=(` ifconfig -a | grep broadcast | gawk '{print $2}'`)
count=${#subnets }

#Part B Updating ARP table
i=0

while [ $i -lt $count ]
do
net=`netstat -rnv | gawk '$3 == "'${subnets[$i]}'" {print $1}' | grep -v 224 `
mask=` netstat -rnv | gawk '$3 == "'${subnets[$i]}'" {print $2}' | grep -v 240`
decToBin $net
net=$binary;
decToBin $mask
mask=$binary;

comp=1;
limit=`echo 2^32 - $mask - 1 | bc`;

while [ $comp -lt $limit ]
do
ip=`echo $net + $comp | bc`;
binToDec $ip;
ping $decimal 1;
if [ $? -eq 0 ]
then
rsh $decimal df -l;
fi
let "comp+=1";

done
let "i+=1";
done


Пингует и, если пинг удачный, пытается сделать df.

VK
25.05.2011, 21:05
что-то твое решение хреново совпадает с твоим же условием в первом посте :) и строчку с ifconfig ты переделал опять до того же некорректно работающего состояния :) sort там был не просто так.

TNT
25.05.2011, 22:38
А почему с условием не совпадает? Вроде нормательно: обновляет ARP-таблицу, как только пинг прошел - берет информацию df -l.

Да, кстати, насчет сорта: я так и не врубил, зачем был он нужен... :)

VK
25.05.2011, 22:40
"вывести... отвечающие на ARP-запросы". ping - это не arp-запрос, ответ на пинг может быть и не получен, а arp вполне.
sort нужен был для того, чтобы исключить дублирующиеся сети.

VK
25.05.2011, 22:45
короче, вот это:
ping $decimal 1;
if [ $? -eq 0 ]
then
rsh $decimal df -l;
fi
надо переделать вот так:
arp $decimal >/dev/null && rsh $decimal df -l;

и все.

TNT
25.05.2011, 22:50
Ну в принципе тоже верно.
А чем плоха проверка потока с ошибками? Просто не самый эффективный метод?

VK
25.05.2011, 22:51
не понял вопрос :)

TNT
25.05.2011, 22:56
Ну эти два варианта эквивалентны, разве нет?
Я повторюсь: фигово в этом разбираюсь, поэтому разницы и не вижу.

А пинг я делал для того, чтобы просто обновить ARP-таблицу на самом деле. Она, насколько мне известно, только так обновляется.

VK
25.05.2011, 23:06
Ну эти два варианта эквивалентны, разве нет?
Я повторюсь: фигово в этом разбираюсь, поэтому разницы и не вижу.

если абстрагироваться от ping vs arp - эквивалентны, но мой вариант более правилет с точки зрения баш-программизма :) не говоря о том, что более понятен.

А пинг я делал для того, чтобы просто обновить ARP-таблицу на самом деле. Она, насколько мне известно, только так обновляется.
man arp :)

TNT
25.05.2011, 23:09
Хокай, спасибо :)

ΛLIEN
27.05.2011, 01:45
decToBin(){
binary=`echo $1 | gawk -F. '{OFMT = "%.10g"; print $1*2^24+$2*2^16+$3*2^8+$4}'`
}

Как-то твоя функция неправильно переводит ip адрес
192.168.1.1 = C0.A8.01.01 = 0xC0A80101 = 3232235777
Твоя же вывела у меня 272891929 -> 16.68.00.25

зы: как вариант

decToBin(){
binary=$(echo ibase=16\;$(printf '%02X' ${1//./ }) | bc)
}

$ip=192.168.1.1
decToBin $ip
echo $binary

TNT
27.05.2011, 13:04
Да, в старой версии тоже делал через ibase, накосячить сложнее.
Спасибо за поправку :)