Тот, у кого больше опыта работы с внутренностями Linux, может меня поправить, но из документации похоже, что они хотят оставить за собой право реализовать sleep()
через alarm()
, что временно установит обработчик для SIGALRM
.
Это не тот SIGCHLD
, который упоминается в фактической документации, но он все равно подпадает под «MT -Небезопасный сигнал».
Если я вас правильно понял, вы хотите проанализировать список IP-адресов и определить, к какой сети класса B или C они принадлежат. Если какая-либо такая сеть встречается более 10 раз, вы хотите напечатать IP-адрес вместе с сетью, к которой он принадлежит, в нотации
.A.B.C.D A.B.0.0/16 n
или
A.B.C.D A.B.C.0/24 n
соответственно в выходной файл spam.lst
, где n
— фактическое количество вхождений в соответствующей подсети.
Предлагаю следующую awk
программу для задачи (назовем ееsort.awk
):
#!/bin/awk -f
BEGIN{
FS=OFS="."
}
NF==4{
if (FNR==NR) {
NF=cl
count[$0]++
next
}
for (n in count) {
if (index($0,n)==1) {
if (count[n]<=th) next
printf "%s %s",$0,n
for (i=cl;i<4;i++) printf ".0"
printf "/%d %d\n",8*cl,count[n]
}
}
}
Вы бы назвали это следующим образом:
awk -v cl=2 -v th=1 -f sort.awk ips.txt ips.txt> spam.lst
Обратите внимание, что входной файл обрабатывается два раза и, следовательно, два раза появляется в качестве аргумента для awk
!
Программа работает следующим образом:
awk
переменную cl
как либо 2
для сети класса B, либо 3
для сети класса C. awk
переменную th
. .
, чтобы разделить входные строки в .
на поля. FNR
счетчик строк файла -равен NR
, глобальному счетчику строк ), мы регистрируем обнаруженные подсети. Для каждой строки номер поля сокращается до значения в cl
, чтобы сократить его до сетевого «базового адреса» класса B или C. Затем счетчик для этого (заново сгенерированного )базового адреса в массиве count
увеличивается, и обработка переходит к следующей строке. count
(, т. е. все подчиненные -сети, зарегистрированные в первом проходе ), чтобы увидеть, начинается ли IP в текущей строке с этого адрес подсети. Если связанный счетчик больше порогового значения, мы выводим текущий IP-адрес,затем базовый адрес, дополненный справа .0
и добавленной маской сети в нотации CIDR, и, наконец, количество вхождений. Вывод для cl=2
, th=1
и приведенный вами пример списка IP-адресов будет выглядеть как
108.61.115.213 108.61.0.0/16 2
108.61.199.100 108.61.0.0/16 2
138.68.224.206 138.68.0.0/16 2
138.68.235.36 138.68.0.0/16 2
148.66.129.250 148.66.0.0/16 2
148.66.130.114 148.66.0.0/16 2
Первоначальное предложение предназначалось для интеграции в существующий сценарий и выглядело следующим образом:
awk -v cl=2 -v nw="8.6.0.0" -F'.' 'BEGIN{split(nw,ref,/\./)} NF==4{for (i=1;i<=cl;i++) {if ($i!=ref[i]) next} printf "%s %s/%d\n",$0,nw,8*cl}' ips.txt
Здесь мы проанализируем список IP-адресов, чтобы проверить, попадают ли они в ту же сеть, что и данный базовый сетевой адрес, указанный с помощью awk
переменной nw
.
ref
. cl
поля текущей строки и эталонного IP-адреса. Если какой-либо из них не совпадает, строка пропускается и обработка переходит к следующей строке. Если все соответствующие поля совпадают, печатается IP-адрес, за которым следует сеть в нотации CIDR. В соответствии с исходным вопросом мне удалось обновить оператор grep, чтобы получить желаемый результат, для всех, кто интересуется только решением bash, поэтому обновленная часть кода выглядит так:
for IPBL in `cat /tmp/IPs`; do
CT=`grep -c "^${IPBL%.[0-9]*.[0-9]*}\." /tmp/IPs`
if [ "$CT" -gt "10" ]; then
echo "$IPBL ${IPBL%.[0-9]*.[0-9]*}.0.0/16 $CT" >>/tmp/spam.lst
fi
done
cat /tmp/spam.lst |sort -n
изменен аргумент формы grep^
-для начала с начала строки и\.
для добавления точки после второго числа в IP-адресе, что дает точное соответствие конкретному диапазону IP-адресов класса B:
"^${IPBL%.[0-9]*.[0-9]*}\."
3.8.35.118 3.8.0.0/16 12
3.8.36.119 3.8.0.0/16 12
3.8.36.121 3.8.0.0/16 12
3.8.37.124 3.8.0.0/16 12
3.8.37.125 3.8.0.0/16 12
3.8.37.126 3.8.0.0/16 12
3.8.37.94 3.8.0.0/16 12
3.8.37.96 3.8.0.0/16 12
3.8.37.97 3.8.0.0/16 12
3.8.37.97 3.8.0.0/16 12
3.8.37.98 3.8.0.0/16 12
3.8.37.98 3.8.0.0/16 12