Eug*_*ash 514 linux networking bash dns
在 Bash 脚本中将主机名解析为 IP 地址的最简洁方法是什么?我正在使用Arch Linux。
Chr*_*own 685
您可以使用getent, 随附glibc(因此您几乎可以肯定在 Linux 上拥有它)。这使用 gethostbyaddr/gethostbyname2 解决,因此还将检查/etc/hosts/NIS/etc:
getent hosts unix.stackexchange.com | awk '{ print $1 }'
Run Code Online (Sandbox Code Playgroud)
或者,正如下面Heinzi说,你可以使用dig与+short参数(查询DNS服务器直接,不看/etc/hosts/ NSS /等):
dig +short unix.stackexchange.com
Run Code Online (Sandbox Code Playgroud)
如果dig +short不可用,以下任何一项都应该有效。所有这些都直接查询 DNS 并忽略其他解析方式:
host unix.stackexchange.com | awk '/has address/ { print $4 }'
nslookup unix.stackexchange.com | awk '/^Address: / { print $2 }'
dig unix.stackexchange.com | awk '/^;; ANSWER SECTION:$/ { getline ; print $5 }'
Run Code Online (Sandbox Code Playgroud)
如果您只想打印一个 IP,则将exit命令添加到awk的工作流程。
dig +short unix.stackexchange.com | awk '{ print ; exit }'
getent hosts unix.stackexchange.com | awk '{ print $1 ; exit }'
host unix.stackexchange.com | awk '/has address/ { print $4 ; exit }'
nslookup unix.stackexchange.com | awk '/^Address: / { print $2 ; exit }'
dig unix.stackexchange.com | awk '/^;; ANSWER SECTION:$/ { getline ; print $5 ; exit }'
Run Code Online (Sandbox Code Playgroud)
man*_*ork 161
随着host从dnsutils包:
$ host unix.stackexchange.com
unix.stackexchange.com has address 64.34.119.12
Run Code Online (Sandbox Code Playgroud)
(根据评论更正了包名。请注意,其他发行版host在不同的包中有:Debian/Ubuntu bind9-host、openSUSE bind-utils、Frugalware bind。)
gre*_*ire 59
我的机器上有一个工具似乎可以完成这项工作。手册页显示它似乎与 mysql 一起......这是你如何使用它:
resolveip -s unix.stackexchange.com
64.34.119.12
Run Code Online (Sandbox Code Playgroud)
如果无法解析主机名,此工具的返回值与 0 不同:
resolveip -s unix.stackexchange.coma
resolveip: Unable to find hostid for 'unix.stackexchange.coma': host not found
exit 2
Run Code Online (Sandbox Code Playgroud)
更新 在 Fedora 上,它带有 mysql-server :
yum provides "*/resolveip"
mysql-server-5.5.10-2.fc15.x86_64 : The MySQL server and related files
Dépôt : fedora
Correspondance depuis :
Nom de fichier : /usr/bin/resolveip
Run Code Online (Sandbox Code Playgroud)
我想它会为您的脚本创建一个奇怪的依赖项...
Hei*_*nzi 51
以下命令 usingdig允许您直接读取结果,无需任何 sed/awk/etc。魔法:
$ dig +short unix.stackexchange.com
64.34.119.12
Run Code Online (Sandbox Code Playgroud)
dig也包含在dnsutils包中。
注意:即使名称无法解析,dig也有返回值0。因此,您需要检查输出是否为空而不是检查返回值:
hostname=unix.stackexchange.com
ip=`dig +short $hostname`
if [ -n "$ip" ]; then
echo IP: $ip
else
echo Could not resolve hostname.
fi
Run Code Online (Sandbox Code Playgroud)
注 2:如果一个主机名有多个 IP 地址(debian.org例如try ),则将返回所有这些地址。到目前为止,这个“问题”影响了这个问题中提到的所有工具:
小智 48
getent hosts unix.stackexchange.com | cut -d' ' -f1
Run Code Online (Sandbox Code Playgroud)
jfg*_*956 32
迄今为止给出的解决方案大多适用于更简单的情况:主机名直接解析为单个 IPv4 地址。这可能是您需要解析主机名的唯一情况,但如果不是,下面将讨论您可能需要处理的某些情况。
Chris Down 和 Heinzi 简要讨论了主机名解析为多个 IP 地址的情况。在这种情况下(以及以下其他情况),假设主机名直接解析为单个 IP 地址的基本脚本可能会中断。下面是一个主机名解析为多个 IP 地址的示例:
$ host www.l.google.com
www.l.google.com has address 209.85.148.147
www.l.google.com has address 209.85.148.103
www.l.google.com has address 209.85.148.99
www.l.google.com has address 209.85.148.106
www.l.google.com has address 209.85.148.105
www.l.google.com has address 209.85.148.104
Run Code Online (Sandbox Code Playgroud)
但什么是www.l.google.com?这是需要引入别名情况的地方。让我们看看下面的例子:
$ host www.google.com
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 74.125.39.103
www.l.google.com has address 74.125.39.147
www.l.google.com has address 74.125.39.105
www.l.google.com has address 74.125.39.99
www.l.google.com has address 74.125.39.106
www.l.google.com has address 74.125.39.104
Run Code Online (Sandbox Code Playgroud)
Sowww.google.com不直接解析为 IP 地址,而是解析为一个别名,该别名本身解析为多个 IP 地址。有关别名的更多信息,请查看此处。当然,别名有单个IP地址的情况也是可以的,如下图:
$ host g.www.ms.akadns.net
g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net has address 207.46.19.190
Run Code Online (Sandbox Code Playgroud)
但是别名可以链接吗?答案是肯定的:
$ host www.microsoft.com
www.microsoft.com is an alias for toggle.www.ms.akadns.net.
toggle.www.ms.akadns.net is an alias for g.www.ms.akadns.net.
g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net.
lb1.www.ms.akadns.net has address 207.46.19.254
$ host www.google.fr
www.google.fr is an alias for www.google.com.
www.google.com is an alias for www.l.google.com.
www.l.google.com has address 74.125.39.147
www.l.google.com has address 74.125.39.103
www.l.google.com has address 74.125.39.99
www.l.google.com has address 74.125.39.106
www.l.google.com has address 74.125.39.104
www.l.google.com has address 74.125.39.105
Run Code Online (Sandbox Code Playgroud)
我没有找到任何主机名解析为不解析为 IP 地址的别名的示例,但我认为这种情况可能会发生。
不仅仅是多个 IP 地址和别名,还有其他一些特殊情况...... IPv6 怎么样?你可以试试:
$ host ipv6.google.com
ipv6.google.com is an alias for ipv6.l.google.com.
ipv6.l.google.com has IPv6 address 2a00:1450:8007::68
Run Code Online (Sandbox Code Playgroud)
其中主机名ipv6.google.com是仅限 IPv6 的主机名。双栈主机名怎么样:
$ host www.facebook.com
www.facebook.com has address 66.220.153.15
www.facebook.com has IPv6 address 2620:0:1c08:4000:face:b00c::
Run Code Online (Sandbox Code Playgroud)
再次关于 IPv6,如果您的主机仅支持 IPv4,您仍然可以解析 IPv6 地址(在仅支持 IPv4 的 WinXP 和 ipv6.google.com 上测试,您可以在 Linux 上尝试)。在这种情况下,解析成功,但 ping 失败并显示未知主机错误消息。这可能是您的脚本编写失败的情况。
我希望这些评论有用。
小智 23
ping -q -c 1 -t 1 your_host_here | grep PING | sed -e "s/).*//" | sed -e "s/.*(//"
Run Code Online (Sandbox Code Playgroud)
无需依赖其他系统即可工作(以及在 /etc/hosts 中指定的主机)
小智 23
为避免别名问题并始终准备好单个 IP 地址以供使用:
python -c 'import socket; print socket.gethostbyname("www.example.com")'
Run Code Online (Sandbox Code Playgroud)
小智 23
简单但有用:
getent ahostsv4 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1getent ahostsv6 www.google.de | grep STREAM | head -n 1 | cut -d ' ' -f 1getent hosts google.de | head -n 1 | cut -d ' ' -f 1如果主机仍然存在,所有命令都将解析 IP 地址。如果主机指向 CNAME,它也会在这种情况下获得 IP。
第一个命令返回解析的 IPv4 地址。
第二个命令返回解析的 IPv6 地址。
第三个命令将返回所有者的首选地址,该地址可以是 IPv4 或 IPv6 地址。
小智 9
这是ping将“未知主机”考虑在内(通过通过 stderr 进行管道tr传输)并用于避免使用正则sed表达式的方法的细微变化:
ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'
Run Code Online (Sandbox Code Playgroud)
如果捕获退出值很重要,那么以下将起作用(虽然不太优雅):
ping -c1 -t1 -W0 www.example.com &>/dev/null && ping -c1 -t1 -W0 www.example.com 2>&1 | tr -d '():' | awk '/^PING/{print $3}'
Run Code Online (Sandbox Code Playgroud)
要完成 Chris Down 的回答,并解决 jfgagne 关于(可能链接的)别名的评论,这里有一个解决方案:
/etc/hosts文件(在我的情况下我不想要它);查询一下,dbernt的python解决方案很完美)不使用 awk/sed
dig +short www.alias.com | grep -v "\.$" | head -n 1
Run Code Online (Sandbox Code Playgroud)始终返回第一个 IP 地址,如果未解析,则返回空字符串。使用 dig 版本:
$ dig -v
DiG 9.8.1-P1
Run Code Online (Sandbox Code Playgroud)
小智 6
php -r "echo gethostbyname('unix.stackexchange.com');"
Run Code Online (Sandbox Code Playgroud)
我希望将此添加为对 Andrew McGregor Re: ping 的评论。但是它不会让我,所以我需要添加这个作为另一个答案。(如果有人可以将其移动到评论中,请随意。)
这是另一种变体,仅使用 ping 和 grep:
ping -q -c1 -t1 your_host_here | grep -Eo "([0-9]+\.?){4}"
Run Code Online (Sandbox Code Playgroud)
grep -E用于扩展正则表达式并
grep -o仅返回匹配部分。正则表达式本身查找一位或多位数字 ( [0-9]+) 和可选的点 ( \.?) 四次 ( {4})
你可以使用host:
hostname=example.org
# strips the IP
IP=$( host ${hostname} | sed -e "s/.*\ //" )
# checks for errors
if [ $? -ne 0 ] ; then
echo "Error: cannot resolve ${hostname}" 1>&2
exit 1;
fi
Run Code Online (Sandbox Code Playgroud)
这是我使用其他人的答案编写的 Bash 食谱 - 首先尝试/etc/hosts,然后回退到 nslookup:
resolveip(){
local host="$1"
if [ -z "$host" ]
then
return 1
else
local ip=$( getent hosts "$host" | awk '{print $1}' )
if [ -z "$ip" ]
then
ip=$( dig +short "$host" )
if [ -z "$ip" ]
then
echo "unable to resolve '$host'" >&2
return 1
else
echo "$ip"
return 0
fi
else
echo "$ip"
return 0
fi
fi
}
Run Code Online (Sandbox Code Playgroud)
nmap -sP 192.168.178.0/24|grep YOUR_HOSTNAME|sed -n 's/.*[(]\([0-9\.]*\)[)].*/\1/p'
Run Code Online (Sandbox Code Playgroud)
是我在没有 DNS 服务器的情况下找到的解决方案
小智 5
dig +noall +answer +nocomments example.com | awk '{printf "%-36s\t%s\n", $1, $5 }'
Run Code Online (Sandbox Code Playgroud)
小智 5
dig 太慢,nslookup 快得多
nslookup google.com | grep -Po 'Address:\s*[0-9.]+' | tail -1 | sed -e 's/Address:\s*//g'
Run Code Online (Sandbox Code Playgroud)