【问题标题】:How can I determine the local machine's IP addresses from Perl?如何从 Perl 确定本地机器的 IP 地址?
【发布时间】:2008-12-01 10:27:37
【问题描述】:

是否有一种干净且独立于操作系统的方法来从 Perl 确定本地计算机的 IP 地址?

到目前为止,我已经找到了以下解决方案:

  • 解析ifconfig和ipconfig的输出(硬,不同windows版本ipconfig输出不同)

  • 建立到已知 IP 的网络连接并检查套接字的本地 IP 地址(如果我无法建立连接将无法工作,并且将只确定一个 IP 地址)

    李>

有更好的建议吗?

【问题讨论】:

  • 幻数是 127.0.0.1
  • 这不是我需要的。我只是想以自定义的形式打印出机器的 IP 地址,我不想使用这些地址。

标签: perl networking


【解决方案1】:

您还有一些other options,包括您的解决方案“建立与已知 IP 的网络连接并检查套接字的本地 IP 地址”。

然而,在那种情况下(建立网络连接),那篇文章指出:

没有主机的 IP 地址这样的东西。
网络接口有 IP 地址,而不是主机,单个网络接口可以有多个(虚拟)IP 地址。操作系统的路由子系统决定使用哪个网络接口和 IP 地址连接到远程机器。

如果你的机器只有一个外网接口,而这个接口只有一个IP地址,那么这个IP地址通常称为机器的地址,但这样不准确。
例如,如果机器通过虚拟接口连接到 VPN,它将使用该接口的 IP 地址连接到 VPN 上的另一台机器,而不是外部 IP 地址

在其他解决方案中:Sys::Hostname - 如果它提供可解析的主机名,则可以使用。

use Sys::Hostname;
use Socket;
my $addr = inet_ntoa((gethostbyname(hostname))[4]);
print "$addr\n";

【讨论】:

  • 这些也是不错的解决方案,但并非在所有情况下都有效。如果没有更好的解决方案,我将创建一个结合这些的自定义解决方案。谢谢。
  • @zb226 感谢您的编辑,非常感谢。
【解决方案2】:

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;

【讨论】:

【解决方案3】:

就我而言,我需要一个没有任何非核心依赖的解决方案。我在研究 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 服务器。

【讨论】:

  • -1 因为复制/粘贴不是使用 Perl 开发的推荐方式。
  • @dolmen 同意。如果它对我的情况有帮助,我编写的脚本被用作 cron 作业,部署到开发箱以保持 DNS 记录处于活动状态。如果我重新访问它,我会考虑将fatpacking Net::Address::IP::Local 改为脚本。 >=D
  • @dolmen 轻松-1。这种东西可以帮助那些不熟悉 perl 而只是想完成它的人。
  • 滥用根域名服务器并且很脆弱,因为这些地址可以而且确实会改变。
【解决方案4】:

要检索所有接口的IP地址,请使用IO::Interface::Simple:

perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'

如果您对 127.0.0.1(环回)不感兴趣,可以过滤 $_->is_loopback。

【讨论】:

    【解决方案5】:

    Perldoc 有一个 answer to this question in its FAQ ("perlfaq9") - 使用不同的模块(它们是标准库的一部分)甚至是内置函数。

    【讨论】:

      【解决方案6】:

      我在 Linux 和 Solaris 上使用 IO::Interface 取得了很好的成功,我认为它甚至可以在 AIX 上运行,但我无法确定。在 search.cpan.org、rt.cpan.org 和 ActiveState 的各种站点上四处寻找,看起来 IO::Interface 可能在 Windows 上遇到构建问题。我想知道它是否可用的唯一方法是在 PPM 中搜索 io-interface。

      【讨论】:

        【解决方案7】:

        使用 WMI?

        Example of extracting IP addresses(在 Powershell 中,但很清楚发生了什么)

        Example of accessing WMI from Perl(不是相同的 WMI 功能,但过程还是相当清晰的)

        编辑:在 Google 代码搜索中搜索 Networkadapterconfiguration 和语言“perl”后:

        Example looks like pretty much what you need

        EDIT2:事实上,OCS 代码似乎包含大多数平台的代码来执行此操作,因此虽然可能没有一组代码可以执行此操作,但您可以重用他们的想法。不过,它是 GPL 的。

        例如,here's the Solaris code。其他位包括 BSD、Linux、MacOS...

        【讨论】:

        • 看起来很有希望,但是 afaik WMI 在大多数 linux 系统上不可用。当然你可以使用 OpenPegasus,但这对于这个问题来说有点太大了。
        • 不,WMI 不会。看起来您可能需要打开操作系统类型并使用不同的代码。
        • 如果没有其他帮助,我会这样做。谢谢你的回答。
        • Google 代码搜索链接已损坏。
        • 是的。谷歌代码搜索已不复存在。我没有更新的来源
        【解决方案8】:
        【解决方案9】:

        Net::Address::IP::Local 工作正常,但由于原始海报要求提供所有本地地址,我认为这个更好:

        http://www.perlmonks.org/?node_id=166951

        在 Windows XP 上使用 ActivePerl 对我来说效果很好。

        【讨论】:

          【解决方案10】:

          对于我使用的窗口

          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 没那么有用。

          【讨论】:

            【解决方案11】:

            我使用了这些 Linux 命令的组合,因此不依赖于任何 perl 模块。

            hostname -i
            hostname -I
            ls /sys/class/net
            ip -f inet addr show eth0| grep -Po 'inet \K[\d.]+'
            

            【讨论】:

              猜你喜欢
              • 2012-07-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-03
              • 1970-01-01
              • 2015-06-22
              • 2013-10-22
              • 1970-01-01
              相关资源
              最近更新 更多