
В настоящее время я запускаю скрипт, который использует nslookup на нескольких хостах, а затем использует awk для печати нужных строк в таблицу. Я печатаю одну строку в file1, а другую в file2, затем использую paste file1 file2 >> file3
для создания этой таблицы.
Таблица выглядит так
Host IP
name 10.10.10.10
name 10.10.10.10
name 10.10.10.10
По большей части это работает. Но по какой-то причине около 20 из моих 160 результатов получают "answer:" в левом столбце, а имя хоста появляется в правом. Вот так:
Host IP
answer: hostname
Это появляется случайным образом в результатах, и я не могу понять, в чем дело, потому что в nslookup нет слова «answer:», которое скрипт мог бы случайно выдать.
Вот мой сценарий для справки:
hosts='hosts.list'
filelines=`cat $hosts`
Empty_Containers(){
truncate -s 0 tmp.txt
truncate -s 0 file1
truncate -s 0 file2
}
for h in $filelines ;
do
Empty_Containers
nslookup $h > tmp.txt
if grep -q "NXDOMAIN" tmp.txt
then
cat tmp.txt | awk 'FNR ==4 {print$5}' > file1
echo "Did_Not_Resolve" > file2
paste file1 file2 >> i.txt
else
cat tmp.txt | awk 'FNR ==4 {print$2}' > file1
cat tmp.txt |awk 'FNR ==5 {print$2}' > file2
paste file1 file2 >> i.txt
fi
cat i.txt | column -t 2 i.txt
done
решение1
Если вашей целью является просто создание таблицы имен хостов и IP-адресов, и вас не особенно волнует использование nslookup
, я, по-видимому, смог создать желаемый вами вывод с помощью быстрого for .. echo
цикла:
for h in $( cat hosts.list ); do
a=$(dig +short $h | head -n1)
echo -e "$h\t${a:-Did_Not_Resolve}"
done
dig
немного более удобный для скриптования инструмент DNS, чем nslookup
, использование +short
опции делает вывод еще чище. Вывод запроса, для которого нет записи, представляет собой пустую строку, поэтому я использую встроенное bash
расширение параметра по умолчанию ( ${var:-default}
) для обработки случая отсутствия записи, что дает ответ "по умолчанию" Did_Not_Resolve
.
$ dig www.example.com
; <<>> DiG 9.10.6 <<>> www.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23579
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;www.example.com. IN A
;; ANSWER SECTION:
www.example.com. 20308 IN A 93.184.216.34
;; Query time: 28 msec
;; SERVER: 172.28.8.1#53(172.28.8.1)
;; WHEN: Fri Jun 01 12:02:27 MST 2018
;; MSG SIZE rcvd: 60
$ dig +short www.example.com
93.184.216.34
Конечный выход составляет:
www.example.com 93.184.216.34
www.google.com 172.217.14.68
host.doesnotexist.tld Did_Not_Resolve
unix.stackexchange.com 151.101.129.69
Альтернативой dig
также является host
:
$ for h in $(cat hosts.list); do host $h; done
www.example.com has address 93.184.216.34
www.example.com has IPv6 address 2606:2800:220:1:248:1893:25c8:1946
www.google.com has address 216.58.193.196
www.google.com has IPv6 address 2607:f8b0:4007:80d::2004
Host host.doesnotexist.tld not found: 3(NXDOMAIN)
unix.stackexchange.com has address 151.101.129.69
unix.stackexchange.com has address 151.101.1.69
unix.stackexchange.com has address 151.101.65.69
unix.stackexchange.com has address 151.101.193.69
В ответ на вопросы в комментарии ниже:
Единственный вариант, который я использую для dig
— это +short
, который сокращает вывод до IP-адреса для данного хоста или пустой строки в противном случае. Я запускаю dig
в подоболочке ( $( dig [...] )
), потому что я захватываю его вывод и присваиваю его переменной a
(для «адреса»). Я передаю вывод dig
через head -n1
, поскольку некоторые хосты (например, хост unix.stackexchange.com
возвращает несколько IP-адресов; для простоты я просто беру первый.
Причина, по которой это вынесено в переменную, заключается в том, что мы можем использовать простой трюк с расширением параметров, чтобы предоставить текст «Не решено» вместо пустой строки, как описано ранее в настоящем документе.
Расширяя, как и просили, данное echo
заявление, в частности:
echo -e "$h\t${a:-Did_Not_Resolve}"
- Переключатель
-e
сообщаетecho
, что я буду использоватьепоследовательности экранирования. В этом случае я использую\t
, который в сочетании с-e
становится Tabа не буквальным экранированнымt
. $h
как и следовало ожидать, просто заменяется содержимым переменнойh
.\t
, как объяснялось ранее, становится Tab.${a:-Did_Not_Resolve}
. Ах, вот где магия.bash
имеет возможность при расширении параметров делать небольшую интроспекцию как часть процесса. Синтаксис${var:-default}
расширяется до содержимого переменнойvar
или, если это не установлено или равно нулю, предоставленная замена (в этом примере,default
; или в реальном случае использования здесь,Did_Not_Resolve
). Вы можете найти более подробную информацию об этом наbash
странице руководства, в разделе под названием «Расширение параметров».
Конечным результатом этого является вывод на каждой строке в следующем порядке имени хоста, a Tabи либо адреса, если он был, либо текста, Did_Not_Resolve
если его не было.