如何获取与默认网关关联的本地IP地址

在服务器上可能有多个networking接口,例如lo,eth0,eth1

路由表中,我知道eth0连接到默认网关。 默认网关的地址,例如,是192.168.1.1。 eth0的地址是192.168.1.100。

我怎样才能得到地址“192.168.1.100”? 任何方法都可以:Python,Shell,UNIX C API …

目前我只能想到一种方法:

  1. 执行命令“route”并得到最后一行(默认192.168.1.1 0.0.0.0 …)
  2. 执行命令“ifconfig”并获取地址列表(127.0.0.1,192.168.1.100,…)
  3. find与默认网关(192.168.1.1)在同一子网中的地址
  4. 那我们得到地址192.168.1.100

有更好的解决scheme吗?

PS:有人build议我们可以在udp socket上调用connect(),然后调用getsockname()来得到本地地址。 但是,它只适用于部分服务器。

@EEAA

所以这是我的脚本:

route -n | awk '$1 == "0.0.0.0" { print $2 }' > gateway.tmp ip -4 addr show | grep inet | awk '{ print $2 }' > addrs.tmp 

第一行打印默认网关:

 10.1.40.1 

第二行打印接口地址列表(以cidr表示法):

 127.0.0.1/8 10.1.46.122/21 

然后我必须决定哪个networking10.1.40.1属于。 所以我写了一个Python脚本:

 import sys def ip_to_binary(ip): bytes = ip.split(".") a = int(bytes[0]) b = int(bytes[1]) c = int(bytes[2]) d = int(bytes[3]) return "{0:08b}{1:08b}{2:08b}{3:08b}".format(a, b, c, d) def mask_to_binary(bits): return "1" * bits + "0" * (32 - bits) def binary_and(a, b): if len(a) == len(b): result = "" for i in range(0, len(a)): if a[i] == "1" and b[i] == "1": result += "1" else: result += "0" return result return None def ip_in_net(ip, net_cidr_notation): net_addr, bits = net_cidr_notation.split("/") bin_mask = mask_to_binary(int(bits)) bin_net = ip_to_binary(net_addr) bin_ip = ip_to_binary(ip) if binary_and(bin_ip, bin_mask) == binary_and(bin_net, bin_mask): return True return False # usage: python autoaddr.py gateway_file addrs_file gateway = open(sys.argv[1]).readline().strip() addrs = open(sys.argv[2]).readlines() for addr in addrs: if ip_in_net(gateway, addr): print addr.split("/")[0] 

为了避免额外的依赖,我没有使用像netaddr和ipaddress这样的库。 最后,我必须将Python脚本添加到Shell脚本中:

 python autoaddr.py gateway.tmp addrs.tmp > auto.tmp rm -f gateway.tmp rm -f addrs.tmp 

现在我有一个文件auto.tmp包含自动生成的地址:

 10.1.46.122 

为什么不是这样的:

 $ ip -4 addr show eth0 | grep inet | awk '{ print $2 }' 192.168.1.100/24 

仅供参考, ifconfig已弃用。 你应该开始使用各种ip命令来代替之前使用ifconfig地方。