用于从主机名列表中获取 IP 并合并到单个文件中的脚本/命令

用于从主机名列表中获取 IP 并合并到单个文件中的脚本/命令

这似乎超出了我目前的技能,因为我已经尝试了一段时间但没有取得太大进展。

我被要求获取主机和 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,对其中的每个条目应用hostawk命令,并将结果保存到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 号码列表添加到该行的末尾。

相关内容