Использование awk для поиска в обратном направлении по строке и добавления результата к следующей строке

Я пытаюсь создать временный файл hosts на основе журнала DNS, предоставленного dnsmasq. У меня это в основном работает, однако у меня проблема с CNAME. Я покажу, чего я достиг на данный момент.

В журнале есть 3 типа ответов, которые мне нужно получить. Самый простой очень легко извлечь из журнала, например

Jun 20 14:27:59 dnsmasq[2551]: reply stackoverflow.com is 64.34.119.12

Это можно вывести на «64.34.119.12 stackoverflow.com», используя

grep reply /tmp/dnslog | grep -v 'NXDOMAIN\|NODATA' | awk '{print $8 " " $6}'

Другой тип журнала относится к CNAME, вот один пример;

Jun 20 14:42:11 dnsmasq[2551]: reply www.videolan.org is <CNAME>
Jun 20 14:42:11 dnsmasq[2551]: reply ganesh.videolan.org is 88.191.250.2

Это можно вывести на «88.191.250.2 ganesh.videolan.org www.videolan.org», используя

grep reply /tmp/dnslog | grep -v 'NXDOMAIN\|NODATA' | awk '{print $8 "\t" $6}' | awk '/CNAME/ {name=$2; getline ; print $0 " " 'name'}'

Однако этот метод не работает для следующего типа журнала, в котором есть несколько CNAME.

Jun 20 15:00:42 dnsmasq[2551]: reply en.wikipedia.org is <CNAME>                        
Jun 20 15:00:42 dnsmasq[2551]: reply wikipedia-lb.wikimedia.org is <CNAME>              
Jun 20 15:00:42 dnsmasq[2551]: reply wikipedia-lb.esams.wikimedia.org is 91.198.174.225

Предыдущая команда дает следующий результат

<CNAME> wikipedia-lb.wikimedia.org      en.wikipedia.org

При использовании первой команды, упомянутой вместе со второй, wikipedia-lb.esams.wikimedia.org связывается с 91.198.174.225, однако wikipedia-lb.wikimedia.org не связывается с wikipedia-lb.esams.wikimedia.org. Идеальный результат должен быть следующим

91.198.174.225 wikipedia-lb.esams.wikimedia.org wikipedia-lb.wikimedia.org      en.wikipedia.org

Чтобы решить эту проблему, я считаю, что файл нужно будет прочитать в обратном порядке, однако не испортит ли это часть getline awk, чтобы добавить к следующей строке?

В идеале я хотел бы объединить оба типа лога в команду, которая бы потом все выводила, а не запускать оба скрипта по отдельности. Может ли кто-нибудь помочь исправить команду awk для этого?

Вот пример «grep response /var/dnslog» и желаемый файл hosts для вывода. Есть и другие вопросы, которые на данный момент являются второстепенными. Они выделены в выводе требуемых хостов.

Jun 20 15:28:21 dnsmasq[2551]: reply photos-a.ak.fbcdn.net is <CNAME>
Jun 20 15:28:21 dnsmasq[2551]: reply photos-a.ak.facebook.com.edgesuite.net is <CNAME>
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.25
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.48
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.64
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.9
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.26
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.51
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.8
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.50
Jun 20 15:28:21 dnsmasq[2551]: reply a995.dspmm1.akamai.net is 213.200.108.65
Jun 20 15:28:22 dnsmasq[2551]: reply stackoverflow.com is 64.34.119.12
Jun 20 15:29:41 dnsmasq[2551]: reply www.wikipedia.org is <CNAME>
Jun 20 15:29:41 dnsmasq[2551]: reply wikipedia-lb.wikimedia.org is <CNAME>
Jun 20 15:29:41 dnsmasq[2551]: reply wikipedia-lb.esams.wikimedia.org is 91.198.174.225
Jun 20 15:29:42 dnsmasq[2551]: reply en.wikipedia.org is <CNAME>
Jun 20 15:29:42 dnsmasq[2551]: reply wikipedia-lb.wikimedia.org is <CNAME>
Jun 20 15:29:42 dnsmasq[2551]: reply wikipedia-lb.esams.wikimedia.org is 91.198.174.225
Jun 20 15:29:42 dnsmasq[2551]: reply ja.wikipedia.org is <CNAME>
Jun 20 15:29:42 dnsmasq[2551]: reply wikipedia-lb.wikimedia.org is <CNAME>
Jun 20 15:29:42 dnsmasq[2551]: reply wikipedia-lb.esams.wikimedia.org is 91.198.174.225

файл hosts

213.200.108.26  a995.dspmm1.akamai.net photos-a.ak.facebook.com.edgesuite.net photos-a.ak.fbcdn.net 
##ideally select 1 host at random from multiple of a995.dspmm1.akamai.net, although list may be randomised already so 1st will suffice##
64.34.119.12    stackoverflow.com
91.198.174.225  wikipedia-lb.esams.wikimedia.org wikipedia-lb.wikimedia.org www.wikipedia.org
91.198.174.225  wikipedia-lb.esams.wikimedia.org wikipedia-lb.wikimedia.org en.wikipedia.org
91.198.174.225  wikipedia-lb.esams.wikimedia.org wikipedia-lb.wikimedia.org ja.wikipedia.org 
##Ideally, detect these similarities for wikipedia and convert the 3 lines into this;##
91.198.174.225  wikipedia-lb.esams.wikimedia.org wikipedia-lb.wikimedia.org www.wikipedia.org en.wikipedia.org ja.wikipedia.org

Предполагается, что файл будет распространяться по каналу с низкой пропускной способностью и высокой задержкой, поэтому файл должен быть как можно меньше. Я знаю, что использование этого файла в течение длительного периода времени вызовет множество проблем, я настроил файл так, чтобы он был действителен только в течение короткого периода времени. Если кто может помочь с обозначенными проблемами, буду очень признателен. Кроме того, у меня есть ограниченный набор доступных UNIX-приложений. Если вышеперечисленное может быть достигнуто в awk, это было бы предпочтительнее. Заранее спасибо!


person Matthew    schedule 20.06.2012    source источник


Ответы (2)


Использование awk с sort:

..|awk '{if($8 ~ /<CNAME>/){load=load" "$6}else{print $8" "load" "$6;load=""}}'
  | sort -u -k2
person Prince John Wesley    schedule 20.06.2012
comment
Большое спасибо! Устройство, которое я использую, не имеет команды сортировки, но я использовал | awk '!x[$2]++', чтобы исправить это. Это нормально с точки зрения эффективности и т.д.? Возможно ли также объединить в основном повторяющиеся строки, такие как пример из Википедии, приведенный в образце? Спасибо - person Matthew; 20.06.2012

Звоните с помощью awk -f parse.awk dnsmasq.log.

/reply/ { 
    host = $6;
    ip = $8;

    names[length(names)+1] = host;

    if (ip !~ /CNAME/) {
    # assign all names up to now the same IP
    # This will overwrite any previous IP assignment as well
    for (i in names) IPs[names[i]] = ip;
    delete names;
    }
}

END {
    # collate hostnames for a particular IP
    for (host in IPs) hosts[IPs[host]] = hosts[IPs[host]]" "host;
    for (IP in hosts) print IP hosts[IP];
}
person chthonicdaemon    schedule 06.09.2012