Как я могу получить IP-адрес eth0 в Python?
При возникновении ошибки в Python script в Unix отправляется электронное письмо.
Мне было предложено добавить {Testing Environment} в строку темы письма, если IP-адрес 192.168.100.37, который является сервером тестирования. Таким образом, мы можем иметь одну версию script и способ узнать, поступает ли почта из испорченных данных на тестовом сервере.
Однако, когда я google, я продолжаю находить этот код:
import socket
socket.gethostbyname(socket.gethostname())
Однако это дает мне IP-адрес 127.0.1.1. Когда я использую ifconfig
, я получаю это
eth0 Link encap:Ethernet HWaddr 00:1c:c4:2c:c8:3e
inet addr:192.168.100.37 Bcast:192.168.100.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:75760697 errors:0 dropped:411180 overruns:0 frame:0
TX packets:23166399 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:59525958247 (59.5 GB) TX bytes:10142130096 (10.1 GB)
Interrupt:19 Memory:f0500000-f0520000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:25573544 errors:0 dropped:0 overruns:0 frame:0
TX packets:25573544 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:44531490070 (44.5 GB) TX bytes:44531490070 (44.5 GB)
Во-первых, я не знаю, откуда он получил 127.0.1.1, но в любом случае это не то, что я хочу. Когда я google, я продолжаю приходить к тому же синтаксису, Bash сценарии или сетевые файлы, и я пытаюсь использовать стандартные библиотеки.
Итак, как я могу получить IP-адрес eth0 в Python?
Ответы
Ответ 1
Два метода:
Метод # 1 (используйте внешний пакет)
Вам нужно задать IP-адрес, привязанный к вашему интерфейсу eth0
. Это доступно из пакета netifaces
import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print ip # should print "192.168.100.37"
Вы также можете получить список всех доступных интерфейсов через
ni.interfaces()
Метод № 2 (без внешнего пакета)
Здесь можно получить IP-адрес без использования пакета python:
import socket
import fcntl
import struct
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
get_ip_address('eth0') # '192.168.0.110'
Примечание. Определение IP-адреса для определения того, какая среда вы используете, - это взломать. Почти все фреймворки предоставляют очень простой способ установить/изменить переменную среды, чтобы указать текущую среду. Попробуйте и посмотрите на свою документацию. Это должно быть так же просто, как делать
if app.config['ENV'] == 'production':
#send production email
else:
#send development email
Ответ 2
В качестве альтернативы, если вы хотите получить IP-адрес какого-либо интерфейса, который используется для подключения к сети, не зная его имени, вы можете использовать это:
import socket
def get_ip_address():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
Я знаю, это немного отличается от вашего вопроса, но другие могут приехать сюда и найти это еще один полезный. Для этого вам не нужно иметь маршрут до 8.8.8.8. Все, что он делает, это открыть сокет, но не отправлять какие-либо данные.
Ответ 3
Простой подход, который возвращает строку с ip-адресами для интерфейсов:
from subprocess import check_output
ips = check_output(['hostname', '--all-ip-addresses'])
для получения дополнительной информации см. hostname.
Ответ 4
Если вам нужно только работать в Unix, вы можете использовать системный вызов (ref. Qaru question Разбор ifconfig для получения только моего IP-адреса с помощью Bash):
import os
f = os.popen('ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1')
your_ip=f.read()
Ответ 5
Поскольку большинство ответов используют ifconfig
для извлечения IPv4 из интерфейса eth0, который устарел в пользу ip addr
, вместо этого можно использовать следующий код:
import os
ipv4 = os.popen('ip addr show eth0 | grep "\<inet\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()
ipv6 = os.popen('ip addr show eth0 | grep "\<inet6\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()
UPDATE:
В качестве альтернативы вы можете перенести часть задачи синтаксического анализа на интерпретатор python, используя split()
вместо grep и awk, поскольку @serg указывает в комментарии:
import os
ipv4 = os.popen('ip addr show eth0').read().split("inet ")[1].split("/")[0]
ipv6 = os.popen('ip addr show eth0').read().split("inet6 ")[1].split("/")[0]
Но в этом случае вам нужно проверить границы массива, возвращаемые каждым вызовом split()
.
ОБНОВЛЕНИЕ 2:
Другая версия с использованием регулярного выражения:
import os
import re
ipv4 = re.search(re.compile(r'(?<=inet )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]
ipv6 = re.search(re.compile(r'(?<=inet6 )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]
Ответ 6
попробуйте под кодом, он работает для меня в Mac10.10.2:
import subprocess
if __name__ == "__main__":
result = subprocess.check_output('ifconfig en0 |grep -w inet', shell=True) # you may need to use eth0 instead of en0 here!!!
print 'output = %s' % result.strip()
# result = None
ip = ''
if result:
strs = result.split('\n')
for line in strs:
# remove \t, space...
line = line.strip()
if line.startswith('inet '):
a = line.find(' ')
ipStart = a+1
ipEnd = line.find(' ', ipStart)
if a != -1 and ipEnd != -1:
ip = line[ipStart:ipEnd]
break
print 'ip = %s' % ip
Ответ 7
Основываясь на ответе @jeremyjjbrown, еще одна версия, которая убирает за собой, как упоминалось в комментариях к его ответу. Эта версия также позволяет предоставлять другой адрес сервера для использования в частных внутренних сетях и т.д.
import socket
def get_my_ip_address(remote_server="google.com"):
"""
Return the/a network-facing IP number for this system.
"""
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect((remote_server, 80))
return s.getsockname()[0]
Ответ 8
Это сработало для меня
import subprocess
my_ip = subprocess.Popen(['ifconfig eth0 | awk "/inet /" | cut -d":" -f 2 | cut -d" " -f1'], stdout=subprocess.PIPE, shell=True)
(IP,errors) = my_ip.communicate()
my_ip.stdout.close()
print IP
Ответ 9
Найдите IP-адрес первой записи eth/wlan в ifconfig, что RUNNING:
import itertools
import os
import re
def get_ip():
f = os.popen('ifconfig')
for iface in [' '.join(i) for i in iter(lambda: list(itertools.takewhile(lambda l: not l.isspace(),f)), [])]:
if re.findall('^(eth|wlan)[0-9]',iface) and re.findall('RUNNING',iface):
ip = re.findall('(?<=inet\saddr:)[0-9\.]+',iface)
if ip:
return ip[0]
return False
Ответ 10
Это результат ifconfig:
[email protected]:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.2.24 netmask 255.255.255.0 broadcast 192.168.2.255
inet6 fe80::88e9:4d2:c057:2d5f prefixlen 64 scopeid 0x20<link>
ether b8:27:eb:d0:9a:f3 txqueuelen 1000 (Ethernet)
RX packets 261861 bytes 250818555 (239.1 MiB)
RX errors 0 dropped 6 overruns 0 frame 0
TX packets 299436 bytes 280053853 (267.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 74 bytes 16073 (15.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 74 bytes 16073 (15.6 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlan0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether b8:27:eb:85:cf:a6 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[email protected]:~ $
Немного подрезав вывод, имеем:
[email protected]:~ $
[email protected]:~ $ ifconfig eth0 | grep "inet 192" | cut -c 14-25
192.168.2.24
[email protected]:~ $
[email protected]:~ $
Теперь мы можем перейти на python и сделать:
import os
mine = os.popen('ifconfig eth0 | grep "inet 192" | cut -c 14-25')
myip = mine.read()
print (myip)