Есть подсеть, например, 192.168.0.0/30 или шире 10.0.0.0/16.
Как в shell скрипте получить список всех IP адресов от первого "нулевого" до последнего широковещательного?
Список в столбик ли, в строчку ли через разделитель - не важно.Ниже пример, стесняюсь показать, наваял. Как сделать более элегантно и более быстро?
Поскольку скрипт для других целей использует Postgresql, то мне в примере было допустимо использовать Postgresql, иначе конечно было бы лучше :) без такой монструозности.Пример:
#!/bin/bash# PostgreSQL shell
PSQL_PSQL=psql# any valid database
PSQL_DB_NAME="postgres"PSQL_USER="root"
# network id
LAN_ID=192.168.0.0/30ip_first=`${PSQL_PSQL} -qtA -c "SELECT host('${LAN_ID}');" ${PSQL_DB_NAME} ${PSQL_USER}`
ip_last=`${PSQL_PSQL} -qtA -c "SELECT host(broadcast('${LAN_ID}'));" ${PSQL_DB_NAME} ${PSQL_USER}`i=0 ; j=0
while [ $j == 0 ] ; do
insertion_str="SELECT inet '${ip_first}' + ${i}"
ip_middle="$( ${PSQL_PSQL} -qtA -c "${insertion_str}" ${PSQL_DB_NAME} ${PSQL_USER} )"echo "${ip_middle}"
i=$(($i+1))insertion_str="SELECT 'stop_here' AS stop_here WHERE inet '${ip_middle}' = inet '${ip_last}'"
feedback="$( ${PSQL_PSQL} -qtA -c "${insertion_str}" ${PSQL_DB_NAME} ${PSQL_USER} )"
[ "${feedback}" == "stop_here" ] && j=1
done
Результат:
192.168.0.0
192.168.0.1
192.168.0.2
192.168.0.3
>[оверквотинг удален]
> [ "${feedback}" == "stop_here" ] && j=1
>done
>
#!/bin/sh
for i in `seq 1 254`; #подставь свой диапазон
do echo 192.168.0.$i; #подставь свою подсеть
done
>for i in `seq 1 254`; #подставь свой диапазон
>do echo 192.168.0.$i; #подставь свою подсеть
>doneА если 10.20.16.0/20 (шир.веш. 10.20.31.255), то код серьёзно сложнее. Подсети могут произвольно меняться.
Возможно путь должен быть:
4 octet ip decimal -> ip binary -> ip decimal
while true ; do
ip decimal -> ip binary -> 4 octet ip binary -> 4 octet ip decimal
echo "4 octet ip decimal"
ip decimal ++
done
Или использовать готовую, но неизвестную мне утилиту...
По прежнему интересно: кто что более эффективное придумал и сделал.Вычисление ш.в. адреса я не пока не сделал.
Кроме вычисления ш.в. адреса, только shell командами, вот:
#!/bin/bashfunction dec2bin () # converter for a $1 number from decimal number system binary with $2 bits width
{
value=$1
base=2
number_plates=$(($2-1))
result=""i=0
[ $value -eq 0 ] && result="0"
while [ $value -gt 0 ]
do
reminder=$((${value}%${base}))
value=$((${value}/${base}))
result="$reminder$result"
i=$(($i+1))
done
for i in $(seq 0 $number_plates) ; do
[ -z ${result:$i:1} ] && result="0$result"
done
echo -n "$result"
}function ip2dec () # $1 is IPv4, output is the ip decimal value
{
arg_ip=$1
# split to octets; octet1 is left, octet4 is right
octet1="${arg_ip%%.*}" ; arg_ip="${arg_ip#*.}"
octet2="${arg_ip%%.*}" ; arg_ip="${arg_ip#*.}"
octet3="${arg_ip%%.*}" ; arg_ip="${arg_ip#*.}"
octet4="${arg_ip%%.*}"# get single number decimal ip; catenate binary value into single binary number; BASh arithmetic is decimal... value will be auto-converted
(( arg_ip=2#$( dec2bin ${octet1} 8 )$( dec2bin ${octet2} 8 )$( dec2bin ${octet3} 8 )$( dec2bin ${octet4} 8 ) ))echo -n "${arg_ip}"
}ip_first="192.168.0.0"
ip_last="192.168.0.3"# get single number decimal ip
the_ip=$( ip2dec ${ip_first} )
ip_last=$(( $( ip2dec ${ip_last} ) + 1 ))while [ "${the_ip}" != "${ip_last}" ] ; do
#echo -e "\nDecimal:\t${the_ip}"
#echo -e "Binary:\t\t$( dec2bin ${octet1} 8 )$( dec2bin ${octet2} 8 )$( dec2bin ${octet3} 8 )$( dec2bin ${octet4} 8 )"ip_to_print=$( dec2bin ${the_ip} 32 )
(( octet1=2#${ip_to_print:0:8} ))
(( octet2=2#${ip_to_print:8:8} ))
(( octet3=2#${ip_to_print:16:8} ))
(( octet4=2#${ip_to_print:24:8} ))echo -e "4 octet:\t${octet1}.${octet2}.${octet3}.${octet4}"
((the_ip++))
done
>[оверквотинг удален]
>
> (( octet1=2#${ip_to_print:0:8} ))
> (( octet2=2#${ip_to_print:8:8} ))
> (( octet3=2#${ip_to_print:16:8} ))
> (( octet4=2#${ip_to_print:24:8} ))
>
> echo -e "4 octet:\t${octet1}.${octet2}.${octet3}.${octet4}"
> ((the_ip++))
>done
>Сорри, видимо я вас неправильно понял сначала (думал вам надо было просто заполнить много IP-адрес автоматически), на Перле модуль есть, к-й уммет делать то, что вам надо... К сожалению, в названии не уверен, вроде Net::IP хотя не уверен точно..
Классная задачка - сразу захотелось решить. Вот что у меня получилось:
a='10.20.16.0/20';
ip=${a/\/*};mask=${a/*\/};ip_array=(${ip//./ });for((i=0,b=0;i<4;i++));do b=$((b<<8));
b=$((b+ip_array[i]));done;f=$((b&(4294967295<<(32-mask))));l=$((b|(4294967295>>mask)));
while [ $f -le $l ];do for i in 24 16 8 0;do echo -n $(((f&(255<<i))>>i));
[ $i -ne 0 ] && echo -n . || echo;done;f=$((f+1));doneРезультат:
10.20.16.0
10.20.16.1
10.20.16.2
10.20.16.3
10.20.16.4
10.20.16.5
10.20.16.6
10.20.16.7
10.20.16.8
10.20.16.9
...
10.20.31.246
10.20.31.247
10.20.31.248
10.20.31.249
10.20.31.250
10.20.31.251
10.20.31.252
10.20.31.253
10.20.31.254
10.20.31.255PS На всякий - у меня bash-4.0.33
>[оверквотинг удален]
>Возможно путь должен быть:
>
>4 octet ip decimal -> ip binary -> ip decimal
>while true ; do
> ip decimal -> ip binary -> 4 octet ip binary -> 4 octet ip decimal
> echo "4 octet ip decimal"
> ip decimal ++
>done
>
>Или использовать готовую, но неизвестную мне утилиту...утилита эта назыывется ipcalc
а в остальном.... в остальном ... PostgreSQL обладает большим кол-вом функций работы с ip диапазонами
>[оверквотинг удален]
>> echo "4 octet ip decimal"
>> ip decimal ++
>>done
>>
>>Или использовать готовую, но неизвестную мне утилиту...
>
>утилита эта назыывется ipcalc
>
>а в остальном.... в остальном ... PostgreSQL обладает большим кол-вом функций работы
>с ip диапазонамиP.S. бОльшим
Будет работать с башем не меньше 3-й версии.#!/bin/bashread NET WIDTH <<< `tr / ' ' <<< "$1"`
read IP1 IP2 IP3 IP4 <<< `tr . ' ' <<< "$NET"`MASK=$(( (0xffffffff << $((32 - WIDTH))) & 0xffffffff ))
MINADDR=$(( ((IP1 << 24) | (IP2 << 16) | (IP3 << 8) | IP4) & MASK ))
MAXADDR=$(( MINADDR | (0xffffffff ^ MASK) ))printip()
{ echo $(( ($1>>24) )).$(( ($1>>16)&0xff )).$(( ($1>>8)&0xff )).$(($1&0xff)); }while (( MINADDR <= MAXADDR )); do
printip $MINADDR
MINADDR=$((MINADDR+1))
doneВызов:
$ ./ip-list.sh 10.0.0.96/29
10.0.0.96
10.0.0.97
10.0.0.98
10.0.0.99
10.0.0.100
10.0.0.101
10.0.0.102
10.0.0.103Развлекайтесь.
Классное кунг-фу :)