При возникновении ошибки в 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?
Два метода:
Вам нужно задать 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()
Здесь можно получить 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
В качестве альтернативы, если вы хотите получить 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. Все, что он делает, это открыть сокет, но не отправлять какие-либо данные.
Простой подход, который возвращает строку с ip-адресами для интерфейсов:
from subprocess import check_output
ips = check_output(['hostname', '--all-ip-addresses'])
для получения дополнительной информации см. hostname.
hostname
Linux net-tools. Команда имени хоста Mac / BSD не предоставляет эту функциональность. Если вы используете версию для Linux, это, вероятно, самый простой способ сделать это.
Если вам нужно только работать в 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()
Поскольку большинство ответов используют 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()
В качестве альтернативы вы можете перенести часть задачи синтаксического анализа на интерпретатор 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()
.
Другая версия с использованием регулярного выражения:
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]
ip addr
но на самом деле нет необходимости направлять вывод в grep и awk. Python более чем способен анализировать вывод с помощью split ()
-oneline
. "output each record on a single line, replacing line feeds with the '\' character. This is convenient when you want to count records with wc(1) or to grep(1) the output."
попробуйте под кодом, он работает для меня в 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
Найдите 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
Это сработало для меня
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
/etc/hosts
.127.0.1.1
». Вы127.0.0.1
виду "127.0.0.1
"? Потому что это ваш локальный петлевой интерфейс,lo
(вторая запись в вашем выводеifconfig
); и первая запись, если выcat /etc/hosts
.