Как я могу определить IP-адреса локальной машины из Perl?
Существует ли чистый и независимый от операционной системы способ определения IP-адресов локальной машины из Perl?
До сих пор я нашел следующие решения:
Анализ выходных данных ifconfig и ipconfig (жесткий диск, разные версии windows имеют разные выходные данные ipconfig)
Установите сетевое соединение с известным IP и проверьте локальный IP-адрес сокета (не будет работать, если я не могу установить соединение и определю только один IP адрес)
Есть предложения получше?
11 ответов:
Net:: Address:: IP:: Local выглядит многообещающе.
use Net::Address::IP::Local; # Get the local system's IP address that is "en route" to "the internet": my $address = Net::Address::IP::Local->public;
В моем случае мне нужно решение без каких-либо непрофильных зависимостей. Я придумал это после изучения кода в Net:: Address:: IP:: Local:
#!/usr/bin/env perl use strict; use warnings; use IO::Socket::INET; my $local_ip_address = get_local_ip_address(); print "$local_ip_address\n"; # This idea was stolen from Net::Address::IP::Local::connected_to() sub get_local_ip_address { my $socket = IO::Socket::INET->new( Proto => 'udp', PeerAddr => '198.41.0.4', # a.root-servers.net PeerPort => '53', # DNS ); # A side-effect of making a socket connection is that our IP address # is available from the 'sockhost' method my $local_ip_address = $socket->sockhost; return $local_ip_address; }
get_local_ip_address()должна возвращать ту же строку, что иNet::Address::IP::Local->public_ipv4.При желании можно изменить атрибут
PeerAddr(в аргументах конструктора для IO::Socket::INET) на локальный DNS-сервер.
У вас также есть некоторые другие варианты, включая ваше решение "установить сетевое соединение с известным IP-адресом и изучить локальный IP-адрес сокета".
В этом случае (установление сетевого соединения), однако, в этой статье указывается, что:
Не существует такой вещи, как IP-адрес хоста.
Сетевые интерфейсы имеют IP-адреса, а не хосты, и один сетевой интерфейс может иметь много (виртуальных) IP-адресов. Маршрутизация операционной системы подсистема решает, какой сетевой интерфейс и IP-адрес использовать для подключения к удаленной машине.Если ваша машина имеет только один внешний сетевой интерфейс, и этот интерфейс имеет только один IP-адрес, то этот IP-адрес обычно называют адресом машины, но это неточно.
Например, если машина подключена к VPN через виртуальный интерфейс, она будет использовать IP-адрес этого интерфейса для подключения к другой машине на VPN, а не к внешнему IP-адресу. адресСреди других решений: использование "
Sys::Hostname"
(Работает, еслиSys::Hostnameпридумывает разрешимое имя хоста)use Sys::Hostname; use Socket; my($addr)=inet_ntoa((gethostbyname(hostname))[4]); print "$addr\n";
Чтобы получить IP-адрес всех интерфейсов, используйте IO:: Interface:: Simple:
perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'Если вы не заинтересованы в 127.0.0.1 (loopback), вы можете фильтровать по
$_->is_loopback.
Perldoc имеет ответ на этот вопрос в своем FAQ ("perlfaq9") - используя различные модули (которые являются частями стандартной библиотеки) или даже встроенную функцию.
У меня был хороший успех с Io::Interface на Linux и Solaris, и я думаю, что он даже работал на AIX, но я не могу вспомнить наверняка. Ковыряюсь в нем. search.cpan.org, rt.cpan.org и на различных сайтах ActiveState, похоже, интерфейс IO::может испытывать проблемы со сборкой на Windows. Я думаю, что единственный способ узнать, доступен ли он,-это поиск io-интерфейса в PPM.
Использовать WMI?
Пример извлечения IP-адресов (в Powershell, но довольно ясно, что происходит)
Пример доступа к WMI из Perl (не те же функции WMI, но опять же процесс достаточно понятен)
EDIT: после поиска в Google codesearch для Networkadapterconfiguration и языка "perl":
Пример выглядит примерно так, как вам нужно
EDIT2: на самом деле код OCS, похоже, содержит код для большинство платформ делают это, поэтому, хотя может не быть ни одного набора кода, который делает это, вы можете повторно использовать их идеи. Это хоть под GPL,.
Например, Вот код Solaris. Другие биты охватывают BSD, Linux, MacOS...
Net:: Address:: IP:: Local работает нормально, но так как оригинальный плакат запрашивает все локальные адреса, я думаю, что этот лучше:
Http://www.perlmonks.org/?node_id=166951
Он отлично работал для меня с ActivePerl для Windows XP.
Для windows я использую
foreach (split(/\r?\n/,`netstat -r`)) { next unless /^\s+0.0.0.0/; @S = split(/\s+/); # $S[3] = Default Gateway # $S[4] = Main IP }Первая строка, начинающаяся с 0.0.0.0, является шлюзом по умолчанию. Там может быть несколько шлюзов. Строки, начинающиеся с 255.255.255.255, также полезны. команды netstat -R и маршрут печати одинаковые.
Может быть адаптирован для OSX, Linux не так полезен.
Я использовал комбинацию этих команд Linux, так что никакой зависимости от любого модуля perl.
hostname -i hostname -I ls /sys/class/net ip -f inet addr show eth0| grep -Po 'inet \K[\d.]+'
Comments