将主机名解析为IP地址的便携方式

时间:2015-07-08 19:33:08

标签: shell dns sh

我需要在shell脚本中将主机名解析为IP地址。代码必须至少在CygwinUbuntuOpenWrtbusybox)中有效。 可以假设每个主机只有一个IP地址。

示例:

  • 输入

    google.com
    
  • 输出

    216.58.209.46
    

修改 nslookup似乎是一个很好的解决方案,但其输出非常难以预测且难以过滤。这是我的计算机上的结果命令(Cygwin):

>nslookup google.com
Unauthorized answer:
Serwer:  UnKnown
Address:  fdc9:d7b9:6c62::1

Name:   google.com
Addresses:  2a00:1450:401b:800::200e
          216.58.209.78

4 个答案:

答案 0 :(得分:5)

我没有使用OpenWRT或Busybox的经验,但是下面的单行程序将适用于Cygwin或Ubuntu的基本安装:

ipaddress=$(LC_ALL=C nslookup $host 2>/dev/null  | sed -nr '/Name/,+1s|Address(es)?: *||p')

以上适用于nslookup的Ubuntu和Windows版本。但是,它仅在DNS服务器回复一个 IP(v4或v6)地址时才有效;如果返回多个地址,则将使用第一个地址。

解释

LC_ALL=C nslookup在运行LC_ALL命令时设置nslookup环境变量,以便该命令忽略当前系统区域设置并以命令的默认语言(英语)打印其输出。

2>/dev/null可以避免Windows版nslookup发出有关正在打印的非权威服务器的警告。

sed命令查找包含Name的行,然后在有多个IP(v4或6)地址或{{1}时删除短语Addresses:后打印以下行当名称服务器只返回一个地址时。

Address:选项表示不打印行,除非有-n命令p - r`选项意味着使用扩展正则表达式(GNU sed是Cygwin和Ubuntu的默认值) )。

答案 1 :(得分:5)

如果您想在几乎所有现代UNIX上都可以使用现成的东西,请使用Python:

pylookup() {
  python -c 'import socket, sys; print socket.gethostbyname(sys.argv[1])' "$@" 2>/dev/null
}

address=$(pylookup google.com)

对于专用工具,dignslookup更容易使用,而short模式只发出文字答案 - 在本例中为IP地址。要仅获取第一个地址,如果找到多个地址:

# this is a bash-specific idiom
read -r address < <(dig +short google.com | grep -E '^[0-9.]+$')

如果您需要使用POSIX sh或破坏版本的bash(例如使用mingw构建的Git Bash,其中进程替换不起作用),那么您可以使用:

address=$(dig +short google.com | grep -E '^[0-9.]+$' | head -n 1)

dig可用于bind-utils包中的cygwin;由于bind是UNIX上使用最广泛的DNS服务器,bind-utils(由相同的代码库构建)也可用于几乎所有的Unix系列操作系统。

答案 2 :(得分:3)

  

TL; DR; 选项2是我对IPv4地址的首选。调整正则表达式以获得IPv6和/或awk以获得两者。对编辑

中提供的选项2建议使用进行了轻微修改

这是一个非常迟到的答案,但我想我会在这里分享我的解决方案,尤其是因为接受的答案在openWRT上没有对我有用(没有设置最少的python)和other answer错误输出&#34;在逗号后没有找到地址&#34;。

选项1(提供名称服务器发送的最后一个条目的最后一个地址):

nslookup example.com 2>/dev/null | tail -2 | tail -1 | awk '{print $3}'

非常简单直接,并不需要对管道命令进行解释。

虽然,在我的测试中,这总是提供IPv4地址(因为IPv4始终是最后一行,至少在我的测试中。)但是,我读到了nslookup的意外行为。所以,我必须找到一种方法来确保即使订单被撤销也能获得IPv4 - 谢谢regex

选项2(确保获得IPv4):

nslookup example.com 2>/dev/null | sed 's/[^0-9. ]//g' | tail -n 1 | awk -F " " '{print $2}'

说明:

nslookup example.com 2>/dev/null - 查找给定主机并忽略STDERR(2>/dev/null

sed 's/[^0-9. ]//g' - 正则表达式获取IPv4(数字和点,阅读&#39; s&#39;命令here

tail -n 1 - 获取最后1行(alt,tail -1

awk -F " " '{print $2} - 使用&#34;捕获并打印第二行部分&#34;作为字段分隔符

编辑:根据评论进行略微修改,使其更加通用化:

nslookup example.com 2>/dev/null | printf "%s" "$(sed 's/[^0-9. ]//g')" | tail -n 1 | printf "%s" "$(awk -F " " '{print $1}')"

在上面的编辑中,我使用printf命令替换来处理任何不需要的尾随换行符。

答案 3 :(得分:3)

这是我从早期答案中窃取的变体:

nslookup blueboard 2> /dev/null | awk '/Address/{a=$3}END{print a}'

这取决于nslookup返回的匹配行如下所示:

Address 1: 192.168.1.100 blueboard

...只返回最后一个地址。

警告:这根本不处理不匹配的主机名。