在给定目的地的情况下,如何在 LINUX 中获取默认网关?

Posted

技术标签:

【中文标题】在给定目的地的情况下,如何在 LINUX 中获取默认网关?【英文标题】:How do i get the default gateway in LINUX given the destination? 【发布时间】:2010-11-15 08:00:16 【问题描述】:

我正在尝试使用目标 0.0.0.0 获取默认网关

我使用了这个命令:netstat -rn | grep 0.0.0.0

它返回了这个列表:

**Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface<br>
10.9.9.17       0.0.0.0         255.255.255.255 UH        0 0          0 tun0<br>
133.88.0.0      0.0.0.0         255.255.0.0     U         0 0          0 eth0<br>
0.0.0.0         133.88.31.70    0.0.0.0         UG        0 0          0 eth0**<br>

我的目标是使用目的地0.0.0.0 ping 默认网关; 因此,即133.88.31.70;但是由于使用了grep,这个返回了一个列表。

如何仅获取默认网关?我的 bash 脚本需要它来识别网络连接是否正常。

【问题讨论】:

嗯...服务器故障问题? sed/awk 它。 (我真的只是建议使用 sed/awk 吗?颤抖 sed 和 awk?和grep一样吗? @Suezy 顺便说一句,我指的是这个问题属于 ServerFault.com 的事实。不幸的是,我没有足够的声望来投票把它移过来,但是一些 SO-gnome 可能会为我做这件事。 grep 可以被认为是 sed 和/或 awk 的特例(我不记得是哪个)。如果您是 linux 新手(……或根本不),我实际上不推荐它。实际上,想想看,一个小的 perl 脚本可以使用正则表达式匹配为您完成此操作。 实际上我被要求在 bash 上执行此操作,但无论如何,感谢您的建议。 =) 【参考方案1】:

iproute2 包中的ip route 命令可以选择路由,而无需使用awk/grep 等进行选择。

选择默认路由(可能有很多)

$ ip -4 route show default  # use -6 instead of -4 for ipv6 selection.
default via 172.28.206.254 dev wlp0s20f3 proto dhcp metric 600

为特定接口选择下一跳

$ ip -4 route list type unicast dev eth0 exact 0/0  # Exact specificity
default via 172.29.19.1 dev eth0

在有多个默认网关的情况下,您可以选择哪一个被选为到特定目标地址的下一跳。

$ ip route get $(dig +short google.com | tail -1)
173.194.34.134 via 172.28.206.254 dev wlan0  src 172.28.206.66 
    cache

然后您可以使用sed/awk/grep 等提取值。这是使用bashread 内置的示例。

$ read _ _ gateway _ < <(ip route list match 0/0); echo "$gateway"
172.28.206.254

【讨论】:

我喜欢这个,因为 ip 已经输出了正确的行。在此基础上稍作改进的版本是:ip -4 route list 0/0 | cut -d ' ' -f 3 更简洁的是ip r l 0/0 | cut -f3 -d' ' ip route list 0/0ip route show to default 之间有什么区别? @tosh - 从技术上讲,它们是相同的 0.0.0.0/0.0.0.0 是默认路由 - 至于示例 ip route show to default 或者 ip route show default 可能会更明确,我会更新。【参考方案2】:

要获取作为默认网关的 NIC 名称,请使用以下命令:

netstat -rn | grep UG | awk 'print $8'

【讨论】:

【参考方案3】:

以下命令仅使用 bash 和 awk 返回 Linux 主机上的默认路由网关 IP:

printf "%d.%d.%d.%d" $(awk '$2 == 00000000 && $7 == 00000000  for (i = 8; i >= 2; i=i-2)  print "0x" substr($3, i-1, 2)  ' /proc/net/route)

如果您有多个默认网关,只要它们的指标不同(它们应该是..),这甚至应该可以工作。

【讨论】:

如果你也想要接口名称: printf "%d.%d.%d.%d %s" $(awk '$2 == 00000000 && $7 == 00000000 for (i = 8; i >= 2; i=i-2) print "0x" substr($3, i-1, 2) ; print $1' /proc/net/route)【参考方案4】:

对于所有默认网关的列表,请使用mezgani's answer,在此处重复(并略微简化):

/sbin/ip route | awk '/^default/  print $3 '

如果您同时配置了多个网络接口,这将打印多个网关。如果您想按名称选择一个已知的网络接口(例如eth1),只需搜索该除了过滤^default行:

/sbin/ip route |grep '^default' | awk '/eth1/ print $3'

您可以编写一个脚本,将单个网络接口名称作为参数并打印关联的网关:

#!/bin/bash
if [[ $# -ne 1 ]]; then
    echo "ERROR: must specify network interface name!" >&2
    exit 1
fi
# The third argument of the 'default' line associated with the specified
# network interface is the Gateway.
# By default, awk does not set the exit-code to a nonzero status if a
# specified search string is not found, so we must do so manually.
/sbin/ip route | grep '^default' | awk "/$1/ print \$3; found=1 ENDexit !found"

正如 cmets 中所述,这样做的好处是可以设置合理的退出代码,这在更广泛的编程环境中可能很有用。

【讨论】:

【参考方案5】:

这里已经有很多答案了。其中一些是非常特定于发行版的。对于那些发现这篇文章的人正在寻找一种找到网关的方法,但不需要在代码/批处理利用中使用它(就像我一样)...尝试:

traceroute www.google.com

第一跳是您的默认网关。

【讨论】:

【参考方案6】:

适用于任何 linux:

route -n|grep "UG"|grep -v "UGH"|cut -f 10 -d " "

【讨论】:

route -n | awk '$4 == "UG" print $2' 使用相同的想法但不那么 hacky 的东西【参考方案7】:

您可以使用ip 命令获取默认网关,如下所示:

IP=$(/sbin/ip route | awk '/default/  print $3 ')
echo $IP

【讨论】:

如果有多个默认网关怎么办?你的脚本产生了我192.168.1.1 192.168.0.1,这是真的:我有两个通往互联网的网关。但主要的是192.168.1.1。是否应该选择第一个 default 值作为主要(优先)值? @SopalajodeArrierez 在我看来,您应该为您感兴趣的特定接口选择网关,例如/sbin/ip route |grep '^default' | awk '/eth1/ print $3' 当您想知道eth1 的网关时。 ...事实上,我会将其发布为我自己的答案。 @KyleStrand 每个路由条目都有一个“度量”值。较小的优先。有没有办法使用该值来查找默认网关? @StarBrilliant 使用 'awk' 可能有一些方法可以做到这一点,但如果失败了,我建议只编写一个小脚本来解析每一行输出并搜索最小的度量值。 【参考方案8】:
#!/bin/bash

##################################################################3
# Alex Lucard
# June 13 2013
#
# Get the gateway IP address from the router and store it in the variable $gatewayIP
# Get the Router mac address and store it in the variable gatewayRouter
# Store your routers mac address in the variable homeRouterMacAddress
#

# If you need the gateway IP uncomment the next line to get the gateway address and store it in the variable gateWayIP
# gatewayIP=`sudo route -n | awk '/^0.0.0.0/ print $2'` 

homeRouterMacAddress="20:aa:4b:8d:cb:7e" # Store my home routers mac address in homeRouterMac.
gatewayRouter=`/usr/sbin/arp -a`

# This if statement will search your gateway router for the mac address you have in the variable homeRouterMacAddress
if `echo $gatewayRouter | grep "$homeRouterMacAddress" 1>/dev/null 2>&1`
then
  echo "You are home"
else
  echo "You are away"
fi

【讨论】:

【参考方案9】:

/sbin/route |egrep "^default" |cut -d' ' -f2-12 #and 'cut' to taste...

【讨论】:

【参考方案10】:

netstat -rn | grep 0.0.0.0 | awk '打印 $2' | grep -v "0.0.0.0"

【讨论】:

0.0.0.0 如果没有设置网关则显示。如果设置了网关,这将不起作用。【参考方案11】:

这就是我的做法:

#!/bin/sh
GATEWAY_DEFAULT=$(ip route list | sed -n -e "s/^default.*[[:space:]]\([[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+\).*/\1/p")
echo $GATEWAY_DEFAULT

【讨论】:

【参考方案12】:

使用下面的命令:

route -n | grep '^0\.0\.\0\.0[ \t]\+[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*\.[1-9][0-9]*[ \t]\+0\.0\.0\.0[ \t]\+[^ \t]*G[^ \t]*[ \t]' | awk 'print $2'

【讨论】:

【参考方案13】:

另一个perl的东西:

$return = (split(" ", `ip route | grep default`))[2];<br>

注意:在ip 之前和default 之后使用这些反引号

【讨论】:

【参考方案14】:

如果您知道 0.0.0.0 是您的预期输出,并且位于行首,您可以在脚本中使用以下内容:

IP=`netstat -rn | grep -e '^0\.0\.0\.0' | cut -d' ' -f2`

然后引用变量$IP

这里最好使用 awk 而不是 cut... 即:

IP=`netstat -rn | grep -e '^0\.0\.0\.0' | awk 'print $2'`

【讨论】:

此方法的基本点,使用扩展的正则表达式,然后通过 cut 获得所需的字段。但是,您可以使用其他人发布的 awk,但我还没有学习该语言。 @maxwelb 你不需要grepawk。例如:netstat -rn | awk '/^0\.0\.0\.0\./ print $2'.【参考方案15】:

这个简单的 perl 脚本将为您完成。

#!/usr/bin/perl

$ns = `netstat -nr`;

$ns =~ m/0.0.0.0\s+([0-9]+.[0-9]+.[0-9]+.[0-9]+)/g;

print $1

基本上,我们运行 netstat,将其保存到 $ns。然后找到以 0.0.0.0 开头的行。然后正则表达式中的括号将其中的所有内容保存到 $1 中。之后,只需将其打印出来。

如果它被称为 null-gw.pl,只需在以下命令上运行它:

perl null-gw.pl

或者如果您在 bash 表达式中需要它:

echo $(perl null-gw.pl)

祝你好运。

【讨论】:

谢谢! =) 我会试试看.. 至少我知道如何用 Perl 编程。 我知道这已经有好几年了......你的正则表达式的问题是它会匹配任何有 0.0.0.0 后跟 IP 地址的东西。这意味着如果您的网关是 0.0.0.0,那么它将返回 genmask。具体而言,“G”标志表示网关。像这样的东西会更准确:echo $(route -n | perl -ne 'print m/0.0.0.0\s+([0-9]+.[0-9]+.[0-9]+.[0-9]+)\s+0.0.0.0\s+\wG/g')netstat -nrroute -n 之间没有区别

以上是关于在给定目的地的情况下,如何在 LINUX 中获取默认网关?的主要内容,如果未能解决你的问题,请参考以下文章

如何在给定上下文的情况下获取布局充气器?

在 Twilio Programmable Chat 中,在 Laravel 后端,如何在给定频道代码的情况下获取频道成员

如何在给定时间和状态信息的情况下获取当地时区

如何在给定文件扩展名的情况下获取 Qt 图标(QIcon)

如何在给定设备路径的情况下获取 USB_DEVICE_DESCRIPTOR

RSA:在给定公钥的情况下获取指数和模数