我有一个大文件,其中包含 40000 行域名。我想读取该文件并使用dig
(或其他方式)在 DNS 中查找域名的 IP 地址,并将它们打印到另一个文件中。
我该怎么做呢?
编辑:一直在使用一些建议的解决方案对此进行测试。大部分内容都是这样:
#!/bin/bash
> ips.txt
cat test.txt | while read host; do
ip=$(getent hosts "$host")
if [ $? -ne 0 ]; then
echo "Host $host was not resolved.";
continue
fi
ip=$(echo "$ip" | awk '{ print $1 }')
echo "Host: $host, IP: $ip" >> ips.txt
done
这会生成一个空文件。不知道为什么这不起作用。
我尝试了另一种解决方案:
for host in 0.accountkit.com 0.bigclicker.me 0.cdn.ddstatic.com 0.facebook.com 0.fls.doubleclick.net 0.hiveon.net 0.mining.garden
do
# get ips to host using dig
ips=($(dig "$host" a +short | grep '^[.0-9]*$'))
for ip in "${ips[@]}";
do
printf 'allow\t\t%s\n' "$ip"
done
done > allowedip.txt
这将打印 ip 地址,但问题是我需要从文件而不是脚本本身读取 DNS 名称。
答案1
很高兴你说这dig
不是一个要求,因为它不是完成这项工作的最佳工具。
像命令这样的工具host
(许多操作系统有 3 种实现方式:ISC 的 BIND 中的一种、Knot DNS 中的一种和 djbwares 中的一种)以人类可读的形式打印信息,并且必须进行繁琐的后处理如果需要一个简单的机器可读列表,则可以去除无用的信息。
ISCdig
和 Knot DNSkdig
有一个+short
选项,可以对此进行改进(以及dig
/的普通输出kdig
),但仅限于一次在一个域名上调用,需要 shell 脚本中的循环和至少 40,000 个进程来完成这项工作。 (这里的一个答案大约有 160,000 个进程。)
另一个工具是 Daniel J. Bernstein 的dnsip
,它是他的 djbdns 工具集的一部分。您想要做的是单行 via xargs
,因为该工具可以采用多个域名参数:
%cat 域名.list unix.stackexchange.com freebsd.org cr.yp.to % %xargs dnsip < 域名.list 151.101.65.69 151.101.193.69 151.101.1.69 151.101.129.69 96.47.72.84 131.193.32.109 131.193.32.108 %
这在一定程度上减少了进程数。 (快速粗略测试表明,减少了 3 个数量级。我的 40,000 个域名测试列表仅产生了 9 个dnsip
进程。)
dnsipq
当您想要使用非完全限定域名时,有一个工具:
%cat 域名.list UNIX 自由软件 加密货币 % %xargs dnsipq < 域名.list unix.stackexchange.com 151.101.1.69 151.101.193.69 151.101.65.69 151.101.129.69 freebsd.stackexchange.com 151.101.65.69 151.101.193.69 151.101.1.69 151.101.129.69 crypto.stackexchange.com 151.101.1.69 151.101.129.69 151.101.193.69 151.101.65.69 %
进一步阅读
- https://unix.stackexchange.com/a/557555/5132
- 丹尼尔·J·伯恩斯坦 (1999)。
dnsip
。DJBwares。 - 丹尼尔·J·伯恩斯坦 (1999)。
dnsipq
。DJBwares。 - https://unix.stackexchange.com/a/446293/5132
答案2
另一个循环。该命令从 中读取主机名列表,hosts
并将每个主机名及其零个或多个 IPv4 地址写入到 中ips
。我使用制表符 ( ) 将主机与其 IP 地址列表分隔开\t
,每个 IP 地址与下一个 IP 地址之间用空格分隔:
#!/bin/bash
while IFS= read -r host
do
if [[ -n "$host" ]]
then
ips=$(dig +short "$host" | grep '^[[:digit:].]*$' | xargs)
printf "%s\t%s\n" "$host" "$ips"
fi
done <hosts >ips
示例数据:
源文件hosts
bbc.co.uk
google.co.uk
结果文件ips
bbc.co.uk 151.101.192.81 151.101.128.81 151.101.64.81 151.101.0.81
google.co.uk 216.58.213.3
答案3
在单个命令行或小型 bash 脚本中:
while IFS= read -r Domainname; do [ -n "$Domainname" ] && echo "$Domainname: $(dig +short "$Domainname" | tr '\n' ' ')"; done < domainlist.csv
domainlist.csv
这会将包含域名的文件读取到while
循环中。主体仅输出所有非空行。
答案4
这将获取文件 中的每一行hosts.txt
,在主机上执行 DNS 查找并将结果 IP 地址(与主机名一起)写入ips.txt
.请记住,它不会进行并行查找来减少时间,也不会处理无效输入。而且它不处理多个 IP 地址。
至于错误,如果主机名未解析,它将在屏幕上打印错误。不会ips.txt
为该主机写入任何内容。
#!/bin/bash
> ips.txt
cat hosts.txt | while read host; do
ip=$(getent hosts "$host")
if [ $? -ne 0 ]; then
echo "Host $host was not resolved.";
continue
fi
ip=$(echo "$ip" | awk '{ print $1 }')
echo "Host: $host, IP: $ip" >> ips.txt
done