![用于从主机名列表中获取 IP 并合并到单个文件中的脚本/命令](https://linux22.com/image/127869/%E7%94%A8%E4%BA%8E%E4%BB%8E%E4%B8%BB%E6%9C%BA%E5%90%8D%E5%88%97%E8%A1%A8%E4%B8%AD%E8%8E%B7%E5%8F%96%20IP%20%E5%B9%B6%E5%90%88%E5%B9%B6%E5%88%B0%E5%8D%95%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E8%84%9A%E6%9C%AC%2F%E5%91%BD%E4%BB%A4.png)
这似乎超出了我目前的技能,因为我已经尝试了一段时间但没有取得太大进展。
我被要求获取主机和 IP 列表以确保安全,以便对这些服务器进行扫描。hosts.linux
服务器上有一个包含所有主机名的主机列表,只是没有 IP。我正在尝试编写一个脚本,该脚本将从该文件中获取这些名称,然后运行命令(例如host
获取 IP 的命令)。
该命令适用于例如:
host csx-svc-spls-06 | awk '{ print $3 }'
它只返回该服务器的 IP。是否可以从文件中读取、运行命令,然后将服务器名称和 IP 地址一行导出到新文件中?
答案1
我不确定使用 nslookup 而不是 dig 的含义,但我认为这可能有效:
while IFS= read -r i; do
nslookup "$i" | grep '^Name' -A1 |
awk '{print $2}'
echo
done < linux.hosts > outputfile
答案2
dig
有一个+short
选项可以让它产生仅有的生成的 IP 地址,仅此而已。
这段代码:
for h in google.com yahoo.com notfound.nosuch; do
printf '%s = ' "$h"
printf '%s' "$(dig +short "$h")" | tr '\n' ,
echo
done
产生输出:
google.com = 108.177.112.102,108.177.112.139,108.177.112.101,108.177.112.138,108.177.112.100,108.177.112.113
yahoo.com = 98.138.252.38,98.139.180.180,206.190.39.42
notfound.nosuch =
相比之下,这段代码:
for h in google.com yahoo.com notfound.nosuch; do
printf "$h = %s\\n" $(dig +short "$h")
done
产生输出:
google.com = 108.177.112.138
google.com = 108.177.112.100
google.com = 108.177.112.101
google.com = 108.177.112.113
google.com = 108.177.112.139
google.com = 108.177.112.102
yahoo.com = 98.139.180.180
yahoo.com = 206.190.39.42
yahoo.com = 98.138.252.38
notfound.nosuch =
要从文件中读取主机名,请将for
上述代码片段中的行替换为for h in $(cat hostlist.txt); do
— 尽管您可能希望添加一些输入验证。由你决定。
随你挑选。如果您想要其他格式,请评论。
注意:如果全部您想要的是 IP 地址,并且您不关心输出中是否包含主机名,那么全部你需要的是:
dig +short $(cat hostlist.txt)
但请记住,任何未出现在 DNS 中的主机名都将被此命令忽略。
答案3
只需使用您在单个主机上使用的命令迭代列表(稍作修改以包含主机名本身):
while read h; do
host "$h" | awk '{ print $1, $3 }'
done <linux.hosts >outputfile.txt
它从 读取linux.hosts
,对其中的每个条目应用host
和awk
命令,并将结果保存到outputfile.txt
。
或者,如果你愿意的话,可以在一行中:
while read h; do host "$h" | awk '{ print $1, $3 }'; done <linux.hosts >outputfile.txt
以下是一种更通用的方法,它考虑主机名别名和多个 IP 地址,并为提供的文件中的每一行输入生成一行输出:
给定 中的主机列表hostnames.txt
,例如
www.uu.se
www.kth.se
www.su.se
然后,给定一个简短的awk
脚本 ( script.awk
),
/^;/ || NF == 0 { next }
$4 == "CNAME" { cn[$5] = (cn[$5] ? cn[$5] "," $1 : $1) }
$4 == "A" { ip[$1] = (ip[$1] ? ip[$1] "," $5 : $5) }
END {
for (i in ip) {
if (cn[i])
printf("%s (%s) = ", i, cn[i])
else
printf("%s = ", i)
print ip[i]
}
}
命令bash
行
dig +noall +answer -f hostnames.txt | awk -f script.awk
会产生
su.se. (www.su.se.) = 193.11.30.171
www.kth.se. = 130.237.28.40
live.webb.uu.se. (www.uu.se.) = 130.238.7.135,130.238.7.133,130.238.7.134
这会考虑主机名别名和具有多个 IP 地址的主机。主机名别名是括号中的名称。
该dig
命令本身会产生输出
; <<>> DiG 9.4.2-P2 <<>> www.uu.se +noall +answer
;; global options: printcmd
www.uu.se. 300 IN CNAME live.webb.uu.se.
live.webb.uu.se. 300 IN A 130.238.7.134
live.webb.uu.se. 300 IN A 130.238.7.135
live.webb.uu.se. 300 IN A 130.238.7.133
www.kth.se. 600 IN A 130.237.28.40
www.su.se. 300 IN CNAME su.se.
su.se. 300 IN A 193.11.30.171
-f
它通过对主机名列表进行批量查询 ( ) 来实现。
这就是awk
代码解析和总结的内容。
该awk
脚本检测CNAME
主机名别名条目,并为数组中的每个真实主机名保存逗号分隔的别名列表cn
,并执行类似的操作以在数组中保存ip
每个主机名的 IP 地址。
该END
块遍历ip
数组中的主机名并检查它是否有任何别名。如果有,它们会打印在括号中。然后将 IP 号码列表添加到该行的末尾。