在给定目的地的情况下,如何在 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
等提取值。这是使用bash
的read
内置的示例。
$ 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/0
和 ip 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 你不需要grep
和awk
。例如: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 -nr
和 route -n
之间没有区别以上是关于在给定目的地的情况下,如何在 LINUX 中获取默认网关?的主要内容,如果未能解决你的问题,请参考以下文章
在 Twilio Programmable Chat 中,在 Laravel 后端,如何在给定频道代码的情况下获取频道成员