RDP Monster

Linux 查看 IP 地址:ip addr、hostname -I 与 curl

Linux 查看 IP 地址:ip addr、hostname -I 与 curl

用 ip addr 查看 Linux 的 IP 地址

在任何当前的 Linux 发行版上,回答“我的 IP 地址是多少”的命令是来自 iproute2 软件包的 ip。它在所有主流发行版中默认安装,无需 root 即可使用,本文其他命令要么是它的封装,要么已被它取代。最基本的形式会列出每块网卡及其全部地址:

ip addr show
ip a            # same thing, shorter

在只有一块网卡的服务器上,输出如下所示(valid_lft 生存期相关的行已省略):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    inet 203.0.113.25/24 brd 203.0.113.255 scope global eth0
    inet6 2001:db8:1::25/64 scope global
    inet6 fe80::5054:ff:fe12:3456/64 scope link

如何读懂它:

  • 网卡名称。lo 是回环接口,地址始终为 127.0.0.1,只能从本机访问。这里真正的网卡是 eth0;在可预测网卡命名下,它可能显示为 ens3、enp0s3 或 eno1,无线网卡则以 wl 开头。
  • inet 是 IPv4 地址,inet6 是 IPv6 地址。/24 后缀是 CIDR 表示法中的前缀长度,也就是子网掩码 255.255.255.0 的现代写法。
  • scope global 表示该地址在本机之外可路由;scope link(fe80:: 那一行)仅在所连接的网段内有效;scope host 表示回环。
  • state UP 加上 LOWER_UP 表示网卡已启用且链路已连通。state DOWN 或 NO-CARRIER 通常正是网卡完全没有地址的原因。

常用变体:

ip -4 addr                  # IPv4 only
ip -6 addr                  # IPv6 only
ip -br -4 addr              # one line per interface
ip -4 addr show dev eth0    # a single interface

当存在多块网卡时(在运行 Docker 的 VPS 上这很常见),简洁模式(-br)是查看 Linux IP 地址最快的方式:

$ ip -br -4 addr
lo               UNKNOWN        127.0.0.1/8
eth0             UP             203.0.113.25/24
docker0          DOWN           172.17.0.1/16

hostname -I:只看地址

如果你只需要地址,hostname -I(大写 I)会把所有已配置的地址打印在一行中,以空格分隔,不包含回环地址和 IPv6 链路本地地址:

$ hostname -I
203.0.113.25 2001:db8:1::25

有两点需要注意。小写的 hostname -i 是另一回事:它通过 /etc/hosts 和 DNS 解析本机主机名,在 Debian 和 Ubuntu 上通常返回 127.0.1.1。另外,hostname -I 输出地址的顺序没有任何保证,还会包含 docker0 之类的虚拟网桥,因此 hostname -I | awk '{print $1}' 只是给人看的捷径,而不是脚本可靠的“主 IP”。这个选项并非 POSIX 标准:Debian、Ubuntu、Fedora 和 RHEL 都有,但 Alpine 这类基于 BusyBox 的精简镜像可能没有。

ifconfig、nmcli 与 networkctl

ifconfig(已废弃,net-tools)

ifconfig 是老教程里常见的命令。它属于 net-tools,多年来一直被 iproute2 取代,在当前的 Ubuntu、Debian 和 Fedora/RHEL 版本中已不再默认安装。如果它返回 command not found,请改用 ip 或安装该软件包:

sudo apt install net-tools     # Debian / Ubuntu
sudo dnf install net-tools     # Fedora / RHEL / Rocky / Alma
$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 203.0.113.25  netmask 255.255.255.0  broadcast 203.0.113.255
        inet6 fe80::5054:ff:fe12:3456  prefixlen 64  scopeid 0x20<link>

输出可读性不错,但有一个实际限制:ifconfig 每块网卡只显示一个 IPv4 地址。用 ip addr add 添加的辅助地址(在拥有多个公网 IP 的 VPS 上很常见)它完全看不到。

nmcli 与 networkctl

桌面系统以及 Fedora/RHEL 系服务器使用 NetworkManager 管理网络;Ubuntu Server 在 systemd-networkd 之上使用 netplan,许多 VPS 镜像也采用同样的模式。两者都有状态工具,可以在一个区块内显示地址、网关和 DNS:

nmcli device show eth0
nmcli -g IP4.ADDRESS device show eth0     # NetworkManager: just the address field
networkctl status eth0                    # systemd-networkd

-g(--get-values)参数只打印某个字段的原始值,包含前缀长度,非常适合脚本使用。如果你不确定机器使用的是哪一套网络栈,甚至不确定是哪个发行版和版本,请先从命令行确认操作系统版本;答案决定了系统上存在哪个工具。

用 curl 查看公网 IP 地址

上面所有命令报告的都是网卡上配置的地址。在大多数 VPS 上,公网 IPv4 直接分配到网卡,因此它也就是互联网看到的地址。而在家庭、办公室或某些云环境中,网卡上是 RFC 1918 私有段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)的地址,由路由器或 1:1 NAT 在出口做转换。查看公网侧唯一可靠的方式是询问外部服务:

curl -4 icanhazip.com
curl -4 ifconfig.me/ip
curl -4 https://api.ipify.org
curl -6 icanhazip.com          # public IPv6, if the host has one

-4 和 -6 参数强制指定地址族,这在双栈主机上很重要:不加它们时,curl 可能优先使用 IPv6,返回你意料之外的地址。icanhazip.com 自 2021 年起由 Cloudflare 运营,返回纯文本。请把结果理解为“我的流量从哪个地址出去”:在 VPN 或代理之后,它是出口节点的地址,而不是你的 ISP 地址。

IPv6:全局地址与链路本地地址

几乎每块 Linux 网卡都会显示至少一行 inet6,它常被误认为是公网 IPv6 地址。以 fe80:: 开头并标记 scope link 的那一行是链路本地地址:每块网卡都会自动生成一个,它只在所连接的网络内有效,永远无法从互联网访问。公网 IPv6 地址标记为 scope global,并以 2 或 3 开头,因为全局单播地址空间是 2000::/3。

ip -6 addr show scope global
ip -6 route show default

如果第一条命令没有任何输出,说明这台机器没有可路由的 IPv6,curl -6 会失败。桌面系统上标记为 temporary 的额外全局地址来自隐私扩展;服务器会关闭该功能,让地址保持稳定,便于 DNS 和防火墙规则使用。

默认网关、路由与 DNS

光有地址并不能说明机器是否能访问到任何东西。路由表才能说明这一点,用 ip route(简写 ip r)即可打印:

$ ip route
default via 203.0.113.1 dev eth0 proto static
203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.25

default via 那一行是默认网关,即没有更精确路由匹配时所有数据包使用的路由器。第二行是配置地址时由内核添加的;其中的 src 字段是主机在该网络上优先使用的源地址。最实用的技巧正基于此:直接询问内核,对某个目的地址它会使用哪个源地址。

$ ip route get 1.1.1.1
1.1.1.1 via 203.0.113.1 dev eth0 src 203.0.113.25 uid 1000
    cache

根据定义,这个 src 值就是本机通往互联网的出口地址,无论存在多少网卡、网桥或隧道。至于 DNS,/etc/resolv.conf 依然是查看的地方,但在运行 systemd-resolved 的系统上(Ubuntu 18.04 起、较新的 Fedora),它只包含本地存根 127.0.0.53;真正的上游解析器由 resolvectl status 显示,在 NetworkManager 主机上也可以看 nmcli device show 的 IP4.DNS 字段。

脚本编写:把 IP 地址存入变量

交互式输出是给人看的;脚本需要的是一个干净的地址,不带任何多余内容。下面这些写法从最简单到最健壮,都经得起考验:

# One interface, IPv4, prefix length stripped
IP=$(ip -4 -o addr show dev eth0 | awk '{print $4}' | cut -d/ -f1)

# Robust: the source address used to reach the internet
IP=$(ip route get 1.1.1.1 | awk '{for (i=1; i<=NF; i++) if ($i == "src") {print $(i+1); exit}}')

# Same thing with JSON output and jq
IP=$(ip -j route get 1.1.1.1 | jq -r '.[0].prefsrc')

# Public IP, with a timeout so the script never hangs offline
PUBLIC_IP=$(curl -4 -s --max-time 5 https://icanhazip.com)

-o 参数让 ip 每行打印一个地址,从而保证 awk 的字段位置稳定;如果网卡上有多个 IPv4 地址,可加上 head -n 1。-j 参数让 ip 输出 JSON,再由 jq 按名称取字段。凡是要在多台机器上运行的脚本,都优先使用这种形式:网卡名称因主机而异,字段名称却不会变。

命令显示内容适用场景
ip addr / ip -br -4 addr所有网卡、全部地址及状态日常使用,全局视图
hostname -I一行显示所有地址快速查看
ip route get 1.1.1.1通往互联网所使用的源地址脚本、多网卡主机
ifconfig每块网卡一个 IPv4(已废弃)老旧系统、旧教程
curl -4 icanhazip.com互联网看到的公网 IPv4NAT、VPN、确认 VPS 地址

在 VPS 上有什么不同

在拥有独享 IPv4 的 VPS 上,ip -4 addr、hostname -I 和 curl -4 icanhazip.com 应当返回同一个地址,因为公网 IP 直接配置在网卡上,中间没有 NAT。如果三者不一致,说明路径中有东西:服务商侧的 NAT、被遗忘的 VPN 客户端,或是抢占了 hostname -I 第一个位置的 Docker 网桥。

确认地址之后,还要检查两件事。第一,它是否真的可达、开放了哪些端口,这与地址是否已配置是两回事:在内部用 ss -tulpn、在外部用 nmap 检查 Linux 服务器的开放端口。第二,反向 DNS。查询你的地址对应的 PTR 记录:

dig -x 203.0.113.25 +short

全新的 VPS 通常返回服务商的通用名称,或者什么都不返回。如果服务器要发送邮件或对外提供任何公共服务,请设置主机名和反向 DNS 使二者一致;尤其是外发邮件,PTR 记录与 HELO 名称不一致时经常会被拒收。

要把这些命令练成条件反射,最快的办法是拥有一台地址专属且不会变动的服务器。rdp.monster 的 Linux VPS 提供独享 IPv4、完整 root 权限、独享 CPU 与内存、无限流量(公平使用)且无需 KYC,支持加密货币付款,每月 $8.99 起。付款确认后约 10 秒服务器即上线,你在上面运行的第一条 ip -br -4 addr 触手可及。

常见问题

为什么 hostname -I 显示了不止一个 IP 地址?

它会列出每块网卡上配置的所有地址,包括虚拟网桥。
hostname -I 会打印所有网卡上的全部地址,只排除回环地址和 IPv6 链路本地地址,因此装有 Docker、libvirt、VPN 客户端或第二块网卡的机器会显示多个地址。docker0 贡献 172.17.0.1,virbr0 通常是 192.168.122.1,双栈主机还会加上它的全局 IPv6 地址。顺序没有保证。当你需要流量真正出去所用的地址时,请运行 ip route get 1.1.1.1 并读取其中的 src 字段。

为什么 Ubuntu 上 ifconfig 提示 command not found?

ifconfig 属于 net-tools,当前发行版已不再默认安装该软件包。
ifconfig 命令属于 net-tools 软件包,它已被 iproute2 取代,并且不在当前 Ubuntu、Debian 和 Fedora/RHEL 版本的默认安装中。替代命令是随处可用的 ip addr。如果某个脚本或旧习惯确实需要它,可以用 sudo apt install net-tools 或 sudo dnf install net-tools 安装,但要记住 ifconfig 每块网卡只显示一个 IPv4 地址,并且会隐藏通过 ip addr add 添加的辅助地址。

为什么 hostname -i 返回 127.0.1.1?

小写 -i 通过 /etc/hosts 解析主机名,而 Debian 系系统会把主机名映射到 127.0.1.1。
hostname -i 根本不查看网络:它像任何应用程序一样,通过 /etc/hosts 再经 DNS 解析系统主机名。Debian 和 Ubuntu 安装程序会添加一行,把主机名映射到 127.0.1.1,让机器在没有网络时也能解析自己的名称,返回的正是这一行的内容。请改用大写 I 的形式 hostname -I,它读取真实的网卡地址,或者用 ip -4 addr 查看完整信息。

如何查找网络中其他设备的 IP 地址?

用 ip neigh 读取邻居表,或用 nmap -sn 扫描整个子网。
最近与本机交换过数据包的设备都在 ARP/邻居缓存中,可用 ip neigh show 查看(若已安装 net-tools,也可用 arp -a)。若想了解全貌,可对子网做 ping 扫描:nmap -sn 192.168.1.0/24 会列出所有响应的主机,反向 DNS 可用时还会显示名称。请替换成你自己的网络,可从 ip route 中的 scope link 路由读取。在 VPS 上这很少有用,而且扫描相邻地址可能违反服务商的条款。

Adrien Roche, 基础设施与主机托管编辑

系统工程师,拥有 10 年以上运维 Windows Server 和 Linux 集群的经验。Adrien 负责 rdp.monster 的基础设施文档,并撰写关于 RDP、VPS 托管、服务器管理、网络和隐私工具的指南。

注册加入我们的分销商计划

您的信息

如有任何疑问, 点击这里联系我们 !
姓名(必填)
请填写您的邮箱地址,您必须拥有以下网站的账号: dashboard.rdp.monster !

您的公司

如果您有网站,请填写网址
请简要说明您打算如何向客户销售服务,例如在论坛上与人交流推广。

连怪兽都爱吃 cookie!

我们使用 cookie 来改善您的浏览体验、提供个性化的广告或内容,并分析网站流量。点击「接受」即表示您同意我们使用 cookie。