Поведение dig +short
должен ничего не возвращать (null) при выполнении запроса, который не возвращает ответа (ничего общего с тайм-аутом, только определенный нулевой ответ).
Это нормально, если запрос выполняется сам по себе, но в сочетании с параметром -f и запуском пакета запросов это ужасно!
dig +short -f queries.txt
queries.txt:
A somedomain.com
TXT otherdomain.com
A somedomain.com
Теперь, если DNS-сервер ничего не возвращает для TXT otherdomain.com (например, ANSWER: 0), ни тайм-аута или чего-то еще, то вывод вышеуказанной команды dig будет примерно таким:
dig +short -f queries.txt
1.2.3.4
1.2.3.4
т.е. всего две строки. Не подходит для "вставить" и других подобных команд. Вы больше не можете объединять вывод query.txt и рабочий вывод dig.
Здесь можно сделать что-нибудь элегантное?
Нет реального способа сделать +short
делайте то, что вы хотите в этом контексте. Это просто неподходящий инструмент для работы с большими объемами данных.
Решение, которое я нашел, столкнувшись с этой проблемой, заключалось в использовании комбинации фильтров: +noall +question +answer
. +noall
выключает все поля отображения, +question
отображает запрос, сделанный с ;
префикс комментария и +answer
отображает ответ.
Результат выглядит так:
$ dig +noall +question +answer google.com serverfault.com
;google.com. IN A
google.com. 284 IN A 74.125.137.101
google.com. 284 IN A 74.125.137.138
google.com. 284 IN A 74.125.137.102
google.com. 284 IN A 74.125.137.100
google.com. 284 IN A 74.125.137.113
google.com. 284 IN A 74.125.137.139
;serverfault.com. IN A
serverfault.com. 187 IN A 198.252.206.16
Если вы не получите ответа, вы увидите два смежных вопроса. Ты не узнаешь Зачем запрос завершился неудачно, так как этот вывод не отображает RCODE (также +short
), но выходных данных достаточно для анализа большого количества данных и поиска записей, требующих более подробного анализа.
Если вы обнаружите, что проводите массовый анализ обращений DNS, переключите +answer
из за +authority
.
Я думаю, что этот скрипт на питоне подойдет.
from subprocess import Popen, PIPE
def dig(z):
proc = Popen(
args='dig +short {} | head -n 1'.format(z),
shell=True, stdout=PIPE
)
return proc.communicate()[0]
result = dict()
with open('queries.txt') as zones:
for zone in zones.readlines():
zone = zone.rstrip()
result[zone] = dig(zone)
with open('queries.txt', 'w+') as results:
for key, value in result.items():
if value == '':
value = 'no answer\n'
results.write('{} : {}'.format(key, value))
Что-то вроде этого хорошо для вставки, поскольку оно сохранит ровно одну строку вывода для каждой строки ввода в случае, если будет 1 или 0 ответов (чего нет в принятом ответе). Он печатает либо IP, либо исходное полное доменное имя. При необходимости его можно изменить, чтобы распечатать все разрешенные IP-адреса в одной строке, но я знал, что в моем случае есть только один IP.
for i in $(cat list); do
ip=$(dig +short $i)
[ -z "$ip" ] && echo $i || echo $ip
done
Он сохраняет ответ в переменной, а затем проверяет, пуста ли переменная (не отвечает, распечатайте ввод) или не пуста (распечатайте вывод).