我当前正在运行一个脚本,该脚本在一堆主机上使用 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
在大多数情况下,这是有效的。但由于某种原因,我的 160 个结果中约有 20 个在左栏中显示“answer:”,而主机名出现在右侧。像这样:
Host IP
answer: hostname
这是在整个结果中随机出现的,我无法弄清楚,因为 nslookup 在任何地方都没有单词“answer:”,导致脚本意外 awk。
这是我的脚本供参考:
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
是一个比 is 更易于脚本编写的 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
在子 shell ( $( dig [...] )
) 中运行,因为我捕获其输出并将其分配给变量a
(对于“地址”)。我正在dig
通过管道传输某些主机的输出head -n1
(例如主机unix.stackexchange.com
返回多个 IP 地址;为了简单起见,我只获取第一个。
将其拉出到变量中的原因是,我们可以使用简单的参数扩展技巧来提供“未解析”文本来代替空字符串,如本文前面所述。
具体按照声明中的要求进行扩展echo
:
echo -e "$h\t${a:-Did_Not_Resolve}"
- 开关
-e
告诉echo
我将使用e景观序列。在这种情况下,我使用的\t
是,当与 结合时-e
,变成 aTab而不是文字转义t
。 $h
正如您所期望的,只是替换为变量 的内容h
。\t
正如前面所解释的,成为一个选项卡。${a:-Did_Not_Resolve}
。啊,这就是神奇的地方。bash
作为过程的一部分,在进行参数扩展时能够进行一些内省。语法${var:-default}
扩展到变量的内容var
或者,如果未设置或为 null,则提供的替换(在此示例中为 ;default
或在此处的实际用例中为Did_Not_Resolve
)。您可以在bash
手册页中标有“参数扩展”的部分中找到有关此内容的更多详细信息。
最终结果是在每一行上按以下顺序输出主机名、 aTab以及地址(如果有)或文本Did_Not_Resolve
(如果没有)。