簡體   English   中英

Python:在 linux 中獲取本地接口/IP 地址的默認網關

[英]Python: get default gateway for a local interface/ip address in linux

在 Linux 上,如何使用 python 找到本地 ip 地址/接口的默認網關?

I saw the question "How to get internal IP, external IP and default gateway for UPnP", but the accepted solution only shows how to get the local IP address for a network interface on windows.

謝謝。

對於那些不想要額外的依賴並且不喜歡調用子進程的人,這里是你如何通過直接閱讀/proc/net/route自己做的:

import socket, struct

def get_default_gateway_linux():
    """Read the default gateway directly from /proc."""
    with open("/proc/net/route") as fh:
        for line in fh:
            fields = line.strip().split()
            if fields[1] != '00000000' or not int(fields[3], 16) & 2:
                # If not default route or not RTF_GATEWAY, skip it
                continue

            return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))

我沒有要測試的 big-endian 機器,所以我不確定字節序是否取決於您的處理器架構,但如果是,請將< in struct.pack('<L', ... with =所以代碼將使用機器的本機字節序。

為了完整性(並擴展 alastair 的答案),這里是一個使用“netifaces”的示例(在 Ubuntu 10.04 下測試,但這應該是可移植的):

$ sudo easy_install netifaces
Python 2.6.5 (r265:79063, Oct  1 2012, 22:04:36)
...
$ ipython
...
In [8]: import netifaces
In [9]: gws=netifaces.gateways()
In [10]: gws
Out[10]:
{2: [('192.168.0.254', 'eth0', True)],
 'default': {2: ('192.168.0.254', 'eth0')}}
In [11]: gws['default'][netifaces.AF_INET][0]
Out[11]: '192.168.0.254'

“netifaces”的文檔: https ://pypi.python.org/pypi/netifaces/

似乎http://pypi.python.org/pypi/pynetinfo/0.1.9可以做到這一點,但我還沒有測試過。

最新版本的netifaces也可以這樣做,但與pynetinfo不同,它可以在 Linux 以外的系統上工作(包括 Windows、OS X、FreeBSD 和 Solaris)。

def get_ip():
    file=os.popen("ifconfig | grep 'addr:'")
    data=file.read()
    file.close()
    bits=data.strip().split('\n')
    addresses=[]
    for bit in bits:
        if bit.strip().startswith("inet "):
            other_bits=bit.replace(':', ' ').strip().split(' ')
            for obit in other_bits:
                if (obit.count('.')==3):
                    if not obit.startswith("127."):
                        addresses.append(obit)
                    break
    return addresses

你可以這樣得到它(用 python 2.7 和 Mac OS X Capitain 測試,但也應該在 GNU/Linux 上工作):import subprocess

def system_call(command):
    p = subprocess.Popen([command], stdout=subprocess.PIPE, shell=True)
    return p.stdout.read()


def get_gateway_address():
    return system_call("route -n get default | grep 'gateway' | awk '{print $2}'")

print get_gateway_address()

這是我使用python獲取Mac和Linux默認網關的解決方案:

import subprocess
import re
import platform

def get_default_gateway_and_interface():
    if platform.system() == "Darwin":
        route_default_result = subprocess.check_output(["route", "get", "default"])
        gateway = re.search(r"\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}", route_default_result).group(0)
        default_interface = re.search(r"(?:interface:.)(.*)", route_default_result).group(1)

    elif platform.system() == "Linux":
        route_default_result = re.findall(r"([\w.][\w.]*'?\w?)", subprocess.check_output(["ip", "route"]))
        gateway = route_default_result[2]
        default_interface = route_default_result[4]

    if route_default_result:
        return(gateway, default_interface)
    else:
        print("(x) Could not read default routes.")

gateway, default_interface = get_default_gateway_and_interface()
print(gateway)

對於 Mac:

import subprocess

def get_default_gateway():
    route_default_result = str(subprocess.check_output(["route", "get", "default"]))
    start = 'gateway: '
    end = '\\n'
    if 'gateway' in route_default_result:
        return (route_default_result.split(start))[1].split(end)[0]

print(get_default_gateway())

如果您有多個默認網關,這是一個解決方案。

import socket, struct
from pprint import pprint as pp

with open("/proc/net/route") as fh:
    # skip header
    next(fh)
    route_list = []
    for line in fh:
        routes = line.strip().split()
        destination = socket.inet_ntoa(struct.pack("<L", int(routes[1], 16)))
        if destination != "0.0.0.0":
            continue
        gateway = socket.inet_ntoa(struct.pack("<L", int(routes[2], 16)))
        mask = socket.inet_ntoa(struct.pack("<L", int(routes[7], 16)))
        metric = routes[6]
        interface = routes[0]
        route_table = (destination, gateway, mask, metric, interface)
        route_list.append(route_table)
    pp(route_list)

#[('0.0.0.0', '0.0.0.0', '0.0.0.0', '0', 'wlan0'),
# ('0.0.0.0', '192.168.225.1', '0.0.0.0', '1024', 'usb0')]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM