将主机名解析为 IP 地址的便携式方法
Portable way to resolve host name to IP address
我需要在 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
我没有使用 OpenWRT 或 Busybox 的经验,但下面的一行代码应该可以与 Cygwin 或 Ubuntu:
的基本安装一起使用
ipaddress=$(LC_ALL=C nslookup $host 2>/dev/null | sed -nr '/Name/,+1s|Address(es)?: *||p')
以上内容适用于 Ubuntu 和 Windows 版本的 nslookup。但是,它仅在 DNS 服务器回复 one IP(v4 或 v6)地址时有效;如果返回多个地址,将使用第一个地址。
说明
LC_ALL=C nslookup
在 运行 nslookup
命令时设置 LC_ALL
环境变量,以便该命令忽略当前系统区域设置并以命令的默认语言打印其输出(英文).
2>/dev/null
避免了来自 nslookup
的 Windows 版本的关于打印非权威服务器的警告。
sed 命令查找包含 Name
的行,然后在存在多个 IP(v4 或 6)地址时,在删除短语 Addresses:
后打印以下行 -- 或 Address:
当名称服务器只返回一个地址时。
-n
选项表示不打印行,除非有 p
命令while the
-r` 选项表示使用扩展的正则表达式(GNU sed 是 Cygwin 的默认设置和 Ubuntu).
如果您想在几乎所有现代 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 的损坏版本(例如 Git Bash,使用 mingw 构建,其中进程替换不会' t 工作),那么你可以改为使用:
address=$(dig +short google.com | grep -E '^[0-9.]+$' | head -n 1)
dig
可用于 bind-utils
包中的 cygwin;由于 bind
是 UNIX 上使用最广泛的 DNS 服务器,bind-utils
(基于相同的代码库构建)也可用于几乎所有 Unix 系列操作系统。
TL;DR; Option 2 is my preferred choice for IPv4 address. Adjust the regex to get IPv6 and/or awk
to get both. There is a slight edit to option 2 suggested use given in EDIT
好吧,这里的回答太晚了,但我想我会在这里分享我的解决方案,尤其是。因为接受的答案在 openWRT 上对我不起作用(没有 python 最小设置)并且 错误 "no address found after comma".
选项 1(给出名称服务器发送的最后一个条目的最后地址):
nslookup example.com 2>/dev/null | tail -2 | tail -1 | awk '{print }'
非常简单直接,不需要解释管道命令。
尽管在我的测试中这总是提供 IPv4 地址(因为 IPv4 总是最后一行,至少在我的测试中是这样。)但是,我读到了 nslookup
的意外行为。所以,我必须找到一种方法来确保即使顺序颠倒了我也能获得 IPv4 - 谢谢 regex
选项 2(确保您获得 IPv4):
nslookup example.com 2>/dev/null | sed 's/[^0-9. ]//g' | tail -n 1 | awk -F " " '{print }'
解释:
nslookup example.com 2>/dev/null
- 查找给定主机并忽略 STDERR (2>/dev/null
)
sed 's/[^0-9. ]//g'
- 获取 IPv4 的正则表达式(数字和点,阅读 's' 命令 here)
tail -n 1
- 获取最后 1 行 (alt, tail -1
)
awk -F " " '{print }
- 使用“”作为字段分隔符捕获并打印行的第二部分
编辑: 根据评论稍作修改,使其实际上更通用:
nslookup example.com 2>/dev/null | printf "%s" "$(sed 's/[^0-9. ]//g')" | tail -n 1 | printf "%s" "$(awk -F " " '{print }')"
在上面的编辑中,我使用 printf
命令替换来处理任何不需要的尾随换行符。
这是我从早期答案中窃取的变体:
nslookup blueboard 2> /dev/null | awk '/Address/{a=}END{print a}'
这取决于 nslookup 返回的匹配行,如下所示:
Address 1: 192.168.1.100 blueboard
...只有 returns 最后一个地址。
警告:这根本不处理 non-matching 个主机名。
我需要在 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
我没有使用 OpenWRT 或 Busybox 的经验,但下面的一行代码应该可以与 Cygwin 或 Ubuntu:
的基本安装一起使用ipaddress=$(LC_ALL=C nslookup $host 2>/dev/null | sed -nr '/Name/,+1s|Address(es)?: *||p')
以上内容适用于 Ubuntu 和 Windows 版本的 nslookup。但是,它仅在 DNS 服务器回复 one IP(v4 或 v6)地址时有效;如果返回多个地址,将使用第一个地址。
说明
LC_ALL=C nslookup
在 运行 nslookup
命令时设置 LC_ALL
环境变量,以便该命令忽略当前系统区域设置并以命令的默认语言打印其输出(英文).
2>/dev/null
避免了来自 nslookup
的 Windows 版本的关于打印非权威服务器的警告。
sed 命令查找包含 Name
的行,然后在存在多个 IP(v4 或 6)地址时,在删除短语 Addresses:
后打印以下行 -- 或 Address:
当名称服务器只返回一个地址时。
-n
选项表示不打印行,除非有 p
命令while the
-r` 选项表示使用扩展的正则表达式(GNU sed 是 Cygwin 的默认设置和 Ubuntu).
如果您想在几乎所有现代 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 的损坏版本(例如 Git Bash,使用 mingw 构建,其中进程替换不会' t 工作),那么你可以改为使用:
address=$(dig +short google.com | grep -E '^[0-9.]+$' | head -n 1)
dig
可用于 bind-utils
包中的 cygwin;由于 bind
是 UNIX 上使用最广泛的 DNS 服务器,bind-utils
(基于相同的代码库构建)也可用于几乎所有 Unix 系列操作系统。
TL;DR; Option 2 is my preferred choice for IPv4 address. Adjust the regex to get IPv6 and/or
awk
to get both. There is a slight edit to option 2 suggested use given in EDIT
好吧,这里的回答太晚了,但我想我会在这里分享我的解决方案,尤其是。因为接受的答案在 openWRT 上对我不起作用(没有 python 最小设置)并且
选项 1(给出名称服务器发送的最后一个条目的最后地址):
nslookup example.com 2>/dev/null | tail -2 | tail -1 | awk '{print }'
非常简单直接,不需要解释管道命令。
尽管在我的测试中这总是提供 IPv4 地址(因为 IPv4 总是最后一行,至少在我的测试中是这样。)但是,我读到了 nslookup
的意外行为。所以,我必须找到一种方法来确保即使顺序颠倒了我也能获得 IPv4 - 谢谢 regex
选项 2(确保您获得 IPv4):
nslookup example.com 2>/dev/null | sed 's/[^0-9. ]//g' | tail -n 1 | awk -F " " '{print }'
解释:
nslookup example.com 2>/dev/null
- 查找给定主机并忽略 STDERR (2>/dev/null
)
sed 's/[^0-9. ]//g'
- 获取 IPv4 的正则表达式(数字和点,阅读 's' 命令 here)
tail -n 1
- 获取最后 1 行 (alt, tail -1
)
awk -F " " '{print }
- 使用“”作为字段分隔符捕获并打印行的第二部分
编辑: 根据评论稍作修改,使其实际上更通用:
nslookup example.com 2>/dev/null | printf "%s" "$(sed 's/[^0-9. ]//g')" | tail -n 1 | printf "%s" "$(awk -F " " '{print }')"
在上面的编辑中,我使用 printf
命令替换来处理任何不需要的尾随换行符。
这是我从早期答案中窃取的变体:
nslookup blueboard 2> /dev/null | awk '/Address/{a=}END{print a}'
这取决于 nslookup 返回的匹配行,如下所示:
Address 1: 192.168.1.100 blueboard
...只有 returns 最后一个地址。
警告:这根本不处理 non-matching 个主机名。