我需要在shell脚本中将主机名解析为IP地址。代码必须至少在Cygwin
,Ubuntu
和OpenWrt
(busybox
)中有效。
可以假设每个主机只有一个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
答案 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)
对于专用工具,dig
比nslookup
更容易使用,而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和/或
中提供的选项2建议使用进行了轻微修改awk
以获得两者。对编辑
这是一个非常迟到的答案,但我想我会在这里分享我的解决方案,尤其是因为接受的答案在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
...只返回最后一个地址。
警告:这根本不处理不匹配的主机名。