干过运维的朋友应该都有这种经历:服务器跑着跑着网络不通了,机房不让进,只有远程控制台,一屏黑底白字,ifconfig、ip addr、route、arp 轮流敲,好不容易排到问题,改配置文件还得小心翼翼,怕手一抖服务起不来。后来我慢慢养成习惯,凡是能用 NetworkManager 的场景,一律用 nmcli 来管网络,确实省了不少事。nmcli 是 NetworkManager 自带的命令行管理工具,不需要图形界面,几乎集成了网络管理所有常见操作:查看连接、启停网卡、改 IP、配 DNS、加路由,甚至搭建 bond 链路聚合,都可以用它一条条命令搞定。写这篇东西,是想把我平时用得最多的 nmcli 常见操作整理一遍,重点放在真实服务器上一定会遇到的那些场景,尤其是 bond 配置,给刚开始接触 Linux 网络管理的朋友一条比较省心的路子。
1. 为什么我推荐用 nmcli 管网络
1.1 它相当于给 NetworkManager 装了一个命令行开关
NetworkManager 大家不陌生,发行版默认都在跑,桌面环境下右上角那个网络图标就是它的前端。问题是一到服务器上,没有图形界面,那个图标就成了纯资源占用,很多人干脆把它 mask 掉,转头去用 systemd-networkd 或者直接改 ifcfg 文件。
我的观点是:NetworkManager 本身没毛病,问题在于没有好用的交互入口。nmcli 就是这个入口。它直接把 NetworkManager 的管理能力拉到了终端里,连接、设备、Wi-Fi、bond、vlan、桥接,全部可以作为对象来操作。而且 nmcli 的输出是纯文本,方便脚本抓取和自动化,这在批量运维里是刚需。
这里先解释“连接”和“设备”这两个概念,新手经常搞混。设备是物理网卡或者虚拟网卡,比如 eth0、eno1;连接是一组配置参数,比如 IP、网关、DNS,它绑在某一个设备上。你可以先定义很多连接,但只有一个连接能在一个设备上处于激活状态。nmcli connection 管的是连接,nmcli device 管的是设备。把这一层关系搞清楚,后面的命令基本就能对上号了。
1.2 比手改配置文件更安全
传统做法是直接编辑 /etc/sysconfig/network-scripts/ifcfg-eth0(CentOS/RHEL)或者 /etc/network/interfaces(Debian/Ubuntu),改完还要判断要不要重启网络服务。这里有两个痛点:第一,配置文件格式容易记错,单词拼错一个,网卡可能直接起不来;第二,如果同时改了多张网卡,重启一瞬间所有网络全部断开,远程连接直接熔断。
用 nmcli 修改不会立即生效,需要主动执行 nmcli connection up 才会应用,而且在 up 之前你可以通过 nmcli connection show 检查配置是否完整,等于多了一道保险。更重要的是,nmcli 会把你的配置同步写入 NetworkManager 自己的配置存储里,下次 NetworkManager 启动后自动加载,不依赖特定发行版的启动脚本。
1.3 适合哪些场景
我主要在三种场景下用 nmcli。第一种是云服务器和物理服务器初始化,拿到机器后第一件事就是配置静态 IP 和 DNS;第二种是虚拟机里调试网络,比如模拟多网卡和 bond;第三种是自动化运维,把 nmcli 命令写进脚本或 Ansible Playbook。如果你是用笔记本装 Linux 桌面,平时靠 WiFi 联网,nmcli 同样能帮你在终端里连 WiFi、查看信号强度,体验不比图形界面差。
2. nmcli 基础操作:先学会看网络状态
2.1 一条命令看全局
最常用的开局命令是 nmcli general status。它直接告诉你 NetworkManager 整体状态:是不是 running,有没有在管控网络。
执行后的输出类似:
$ nmcli general status STATE CONNECTIVITY WIFI-HW WIFI WWAN-HW WWAN connected full enabled enabled enabled enabledSTATE 是 connected,说明 NetworkManager 正在正常工作;CONNECTIVITY 是 full,表示网络连通性正常。WIFI-HW 表示无线硬件开关,WIFI 是无线功能开关,WWAN 是移动网络,服务器上通常都是 disabled 或 unavailable,不用在意。如果 STATE 显示 running 但 CONNECTIVITY 是 limited,多半是 DHCP 拿不到地址或者 DNS 有问题,排查的时候先看这一行能省下不少时间。
2.2 查看连接列表
nmcli connection show 是用的最多的命令之一。它能列出所有已经定义好的连接,不管连接是否激活。示例输出:
$ nmcli connection show NAME UUID TYPE DEVICE bond0 abc... bond bond0 eno1 def... ethernet eno1注意排在末尾的 DEVICE 列,如果显示为空,说明这个连接没在用了。查看当前活跃的连接,加一个 --active 参数:nmcli connection show --active。这个命令在检查多网卡服务器时特别好用,一眼能看出哪几张网卡正在承载网络流量。
2.3 查看设备状态
nmcli device status 是设备层的总览,输出:
$ nmcli device status DEVICE TYPE STATE CONNECTION eno1 ethernet connected eno1 eno2 ethernet disconnected -- bond0 bond connected bond0STATE 表示设备当前状态,比如 connected、disconnected、unavailable。unavailable 通常意味着物理链路没接上或者驱动有问题。CONNECTION 列是这个设备当前激活的连接名。想查看某块网卡的详细配置,例如 IP、MAC、网关、DNS,用 nmcli device show eno1。这个命令的输出很长,但信息全,尤其在核对双网卡路由的时候比 ip addr 更直观。
2.4 快速启停连接和刷新 DHCP
需要临时断网再恢复,用 nmcli connection up <连接名> 和 nmcli connection down <连接名> 是最直接的。up 会确保该连接被成功激活,如果配置有改动,也会在这时应用;down 会让设备脱离连接,设备状态变成 disconnected。
我在测试网络修改时常用的一个动作是:nmcli connection up bond0 之后紧接着 ping 网关,验证联通性。另外,如果设备处于 connected 但 IP 过期,或者 DHCP 租约异常,可以先用 nmcli connection down 再 up,强制重新走一遍 DHCP。注意 down 当前正在使用的连接会断开网络,远程操作时小心断连,建议配合控制台,或者把修改命令写成脚本批量执行,不要手一抖把自己关在门外。
2.5 无线网卡也不在话下
虽然服务器上无线网卡用得少,但笔记本装 Linux 的时候,nmcli 连 WiFi 比图形界面点来点去更快。扫描热点用 nmcli device wifi list,连接指定 WiFi 用:
nmcli device wifi connect "MyWiFi" password "pass1234"如果机器上有多个无线网卡,可以指定 ifname:
nmcli device wifi connect "MyWiFi" password "pass1234" ifname wlan0想临时开一个热点给手机用,nmcli device wifi hotspot ifname wlan0 ssid "myssid" password "pass1234" 就能搞定。这些操作在调试无线网络时很实用,关键是命令简洁,不依赖桌面环境。
3. 用 nmcli 创建和修改网络连接
前面说过,连接就是一组配置。创建连接需要明确两个关键参数:连接名和设备名。连接名是逻辑名,随便起;设备名是物理接口名,比如 eno1、ens3,必须和系统实际接口对上。查看接口名用 ip link 或者 nmcli device status。
3.1 创建一个静态 IP 连接
假设服务器有两个网卡:eno1 用于业务,eno2 用于管理。现在要给 eno1 配一个静态 IP,比如 192.168.10.100/24,网关 192.168.10.1,DNS 用 223.5.5.5 和 114.114.114.114。
nmcli connection add type ethernet con-name eno1 ifname eno1 \ ipv4.addresses 192.168.10.100/24 \ ipv4.gateway 192.168.10.1 \ ipv4.dns "223.5.5.5 114.114.114.114" \ ipv4.method manual这条命令创建了一个名为 eno1 的 ethernet 类型连接,绑定了 ifname eno1。ipv4.method manual 是核心,表示不使用 DHCP,完全按手动配置来。DNS 可以写多个,用空格分隔,必须用引号包起来。执行后 NetworkManager 会自动生成一个连接配置文件,路径通常是 /etc/NetworkManager/system-connections/eno1.nmconnection。
注意两个容易犯的错:第一,IP 地址必须要写前缀长度,比如 /24 不能丢,丢了你可能拿到一个没有掩码的地址,后续路由各种诡异;第二,con-name 和 ifname 可以相同,也可以不同,但如果像很多教程那样写成 con-name 业务网卡,容易在后期混淆,我建议连接名直接用设备名,或者加一个业务/管理前缀,一目了然。
创建完连接后,还需要激活:
nmcli connection up eno1这时如果原设备上还有另一个活跃连接,它会自动替换掉。如果不放心,可以先 nmcli device status 看看 eno1 的状态。
3.2 创建一个 DHCP 连接
如果网卡不需要固定 IP,比如虚拟机 NAT 网络、DHCP 环境,创建命令更简单:
nmcli connection add type ethernet con-name eno2 ifname eno2 ipv4.method autoipv4.method auto 表示自动获取地址。这里不写 ipv4.addresses 也不会报错。激活后可以用 nmcli device show eno2 看到从 DHCP 拿到的 IP、网关和 DNS。如果发现 DHCP 没有拿到地址,最常见的坑是上游没有开 DHCP 服务,或者虚拟机网卡没有接对网线,先检查这些再折腾命令。
3.3 修改现有连接
需要改 IP 的时候,用 nmcli connection modify 而不是删了重建。常见用法:
nmcli connection modify eno1 \ ipv4.addresses 192.168.10.200/24 \ ipv4.gateway 192.168.10.1 \ ipv4.method manual注意,modify 只是修改配置,不会立刻生效,必须再次 nmcli connection up eno1。另外,如果你新加了一个 IP,而之前已经有一个 IP,默认情况下会把旧 IP 替换掉。如果你希望同时保留多个 IP,可以这样写:
nmcli connection modify eno1 +ipv4.addresses 192.168.10.200/24加了加号表示追加,不加就是覆盖。这个细节很多教程里没写,但实际非常有用。比如服务器需要临时加一个管理网段地址,这招比重新写配置文件快得多。
DNS 的修改也类似:
nmcli connection modify eno1 ipv4.dns "223.5.5.5" nmcli connection modify eno1 +ipv4.dns 114.114.114.114第二行的加号是追加 DNS,注意追加时如果 DNS 里已经存在你写的那个地址,不会重复添加。
3.4 删除连接和整理连接
删连接用:
nmcli connection delete eno1被删除的连接会同时从磁盘和内存中移除,网卡会回到未配置状态,需要重新创建。删除时一定要确认这个连接没有承载当前紧要业务,因为不会二次确认。
如果连接创建错了,但不想完全删除,可以重命名连接:
nmcli connection modify eno1 connection.id 业务网卡修改 connection.id 就能改连接名,名称变了不影响设备绑定。这个操作在批量初始化服务器时很好用,可以先统一用模板名,配置完成后再按业务改成有意义的名字。
4. nmcli 配置 bond:一张网卡挂了,另一张顶上
bond 是文章的重头戏。不少朋友在服务器上遇到网卡冗余的需求。bond 的原理简单说:把多张物理网卡绑成一个逻辑网卡,对外表现成一个 IP 地址,对内由 bond 驱动分担流量或做故障切换。最常见的是两张千兆网卡绑成一个 bond0,一张断了另一张自动接管,业务不中断。
4.1 先说清楚 bond 的几种模式
配置 bond 之前必须选模式,模式选错会导致两张网卡只能一张用,或者流量分配不符合预期。用 nmcli 配置时,mode 参数支持以下几种:
| 模式名称 | 作用 |
|---|---|
| active-backup | 主备模式,同一时刻只有一张网卡工作,主卡故障自动切换备份卡 |
| balance-rr | 轮询模式,数据包轮流从两张网卡发出,带宽利用率高 |
| balance-xor | 基于源目 MAC 的 XOR 计算,性能均衡 |
| broadcast | 广播模式,所有包往所有网卡发,适合特殊环境 |
| 802.3ad | 动态链路聚合,需要交换机支持 LACP 协议 |
| balance-tlb | 发送负载均衡,接收由当前活跃卡负责 |
| balance-alb | 自适应负载均衡,发送和接收都做了负载分配 |
我平时用得最多的是 active-backup 和 802.3ad。服务器没有特殊交换机配置时,active-backup 最省心,两张卡一主一备,不需要交换机配合。如果想提高整体带宽,且交换机确定了开启 LACP,那就用 802.3ad。不要天真地以为 bond 一定能带宽翻倍,balance-rr 虽然可以同时用两张网卡发流,但很多交换机或网络环境并不兼容;balance-alb 对网卡驱动和系统要求也高。保守方案就是在 active-backup 下确保可用性。
4.2 创建 bond 主连接
第一步,创建 bond 逻辑网卡。比如要建一个名为 bond0 的 bond 连接,模式选 active-backup,然后给 bond0 配置静态 IP 192.168.1.50/24:
nmcli connection add type bond con-name bond0 ifname bond0 \ bond.options "mode=active-backup" \ ipv4.addresses 192.168.1.50/24 \ ipv4.gateway 192.168.1.1 \ ipv4.dns "223.5.5.5" \ ipv4.method manual这一步生成的 bond0 连接本身已经带 IP 和网关。注意,如果纯粹想先创建 bond 再单独配网络,也可以不带 ipv4 参数,后面再用 modify 补,但既然一步能做完,我更推荐直接带上。type bond 和 ifname bond0 要分清,type 是设备类型,ifname 是逻辑接口名。
创建完成后可以用 nmcli connection show bond0 看有没有生成,不过此时 bond0 还没有真正工作,因为下面要加入物理网卡。
4.3 把物理网卡加入 bond
接下来需要为每张物理网卡创建一个“子连接”,告诉 NetworkManager 这张网卡属于 bond0。假设服务器有两张物理网卡 eno1 和 eno2:
nmcli connection add type ethernet con-name bond0-port1 ifname eno1 master bond0 nmcli connection add type ethernet con-name bond0-port2 ifname eno2 master bond0注意,master bond0 是关键参数,表示这个 ethernet 连接是 bond0 的成员。不要给这两个成员连接配置 IP,因为 IP 在 bond0 主连接上;如果给成员单独配 IP,会造成地址冲突。创建时不需要指定 mode,mode 在 master 连接上决定。
如果你已经用传统方式创建了成员连接,也可以用 modify 把它挂到 bond 下:
nmcli connection modify bond0-port1 master bond0但前提是原来的连接类型要合适,我这里直接新建更省事。还有一个细节:成员连接的 con-name 不要和物理网卡名一样,我用 bond0-port1 这种格式,看到名字就知道它是哪个 bond 的哪个口,排查问题时比一长串 UUID 舒服多了。
4.4 激活 bond 连接
成员加完后,激活 bond0:
nmcli connection up bond0激活 bond0 时,NetworkManager 会自动把两个成员连接也激活。这时执行 nmcli device status,你会看到 bond0、eno1、eno2 都变成 connected,其中 bond0 的 CONNECTION 列是 bond0,eno1、eno2 的 CONNECTION 列是各自的成员连接名。
马上验证一下逻辑接口是否存在:
ip link show bond0 cat /proc/net/bonding/bond0/proc/net/bonding/bond0 的输出很关键,里面可以看到 Bonding Mode、MII Status、Slave Interface 等信息。MII Status 是 up,Slave Interface 下面列出了 eno1 和 eno2,说明两张网卡都已经被 bond 接管了。
4.5 验证 failover 是否正常
配置完成不能只看状态,必须做故障切换测试。最简单的测试方法:拔掉一张物理网线,或者在系统层面禁用一张网卡:
nmcli device disconnect eno1或者用 ip link set eno1 down。这时再 cat /proc/net/bonding/bond0,应该能看到 active slave 切换到了 eno2,MII Status 还是 up。然后 ping 网关确认网络没有长时间中断。恢复 eno1 用 nmcli device connect eno1。
我实测过,在 active-backup 模式下,故障切换通常在百毫秒级别,但 ping 丢包可能有一到两包,这是正常现象。如果丢包太多甚至断流几十秒,先检查是不是 mode 选错了,或者网卡驱动在切换时被重置。如果成员连接没有自动激活,也可以手动 nmcli connection up bond0-port1 补一下。
5. 配置 bond 和日常维护中的疑难杂症
5.1 注意 bond 与不同网卡驱动、NetworkManager 版本的关系
不同发行版的 NetworkManager 对 bond 的支持程度有细微差别。有些版本中,bond 连接创建时如果不显式指定 connection.autoconnect yes,重启后可能不会自动启用。所以我会在建完 bond 后顺手加一句:
nmcli connection modify bond0 connection.autoconnect yes成员连接也可以加一下,避免重启之后 bond 起来了成员却掉线。另外,如果用的是特定厂商的网卡,驱动里可能还要设置 ethtool 的参数,比如 offload 相关,这些一般不归 nmcli 管,系统初始化时单独配置。遇到网卡模式异常,先用 ethtool eno1 查看网卡速率、自协商状态,别急着改 bond 配置。
5.2 网卡名对不上是最常见的坑
Linux 网卡命名有 udev 规则,有时机器重启后 eno1 和 eno2 的物理对应关系会变,尤其是添加新网卡后,导致 bond 成员接错卡。排查时用 ethtool -p eno1 可以让网卡指示灯闪烁,确认物理位置。还有一个办法是看 /sys/class/net/eno1/device/uevent 里的 PCI 地址,和 lspci 对照。这一步在物理机操作时特别重要,别等到配置完发现 bond 用的是两张无关网卡才后悔。
5.3 常见问题速查
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| nmcli 命令找不到 | NetworkManager 未安装或未启动 | 安装 NetworkManager 并 systemctl enable --now NetworkManager |
| bond0 创建后看不到 | 没有激活连接 | nmcli connection up bond0 |
| bond0 起来了但两张网卡都不通 | IP 配到了成员连接上 | 删除成员上的 ipv4 配置,确保 IP 只在 bond0 |
| 主备切换后 IP 短暂丢失 | ARP 缓存和路由更新需要时间 | 等待几秒或清 ARP 缓存;确认网关在同一网段 |
| balance-rr 模式网速反而变慢 | 交换机不支持或开启了 STP 干扰 | 改回 active-backup 或启用 802.3ad |
| 重启后 bond 没自动起来 | autoconnect 没有启用 | connection.autoconnect yes |
| 删除成员连接后 bond 少了一块网卡 | NetworkManager 没有感知变化 | nmcli connection reload |
这些坑我基本都踩过。尤其是把 IP 配置到成员连接上这个问题,几乎每个新手都会犯:bond 没建好就先给 eno1 配了 IP,然后把 eno1 挂进 bond0,结果 bond0 一直没地址,eno1 又提示 connected,排查了大半天才发现是概念混了。记住一句话:bond 的 IP 只在主连接上,成员连接永远只负责“入队”。
5.4 修改 bond 参数的技巧
如果想修改 bond 模式或参数,比如把 active-backup 改成 802.3ad,不能直接改,先确认交换机支持 LACP,然后再执行:
nmcli connection modify bond0 bond.options "mode=802.3ad,miimon=100"改完要 down 再 up 连接:
nmcli connection down bond0 && nmcli connection up bond0也可以一次指定多个参数。miimon 表示链路监测间隔,单位毫秒,默认是 100,一般可以保守设成 100。数值太大,链路断开后检测会变慢;太小,对网卡和系统中断负担会变大。还有 primary 参数,可以指定主网卡。例如:
nmcli connection modify bond0 bond.options "mode=active-backup,miimon=100,primary=eno1"这样 active-backup 模式下系统会优先用 eno1,eno1 恢复后会自动切回,避免主备来回抖动。修改 bond.options 会整体覆盖原有选项,改之前最好先记一下当前的完整 options 值,以免把之前调好的参数弄丢。
6. 我平时积累的几个 nmcli 小习惯
6.1 批量检查所有连接状态
写脚本的时候,我习惯用 terse 模式输出,方便传给 awk、cut 处理。比如列出所有连接名:
nmcli -t -f NAME connection show这会输出每一行一个连接名。如果要拿设备状态,用:
nmcli -t -f DEVICE,STATE device status输出类似 eno1:connected,数据是以冒号分隔的。字段名记不住可以先看 nmcli help 或者 nmcli connection --help。批量巡检时把这些命令套进 for 循环,效率比一条条人肉看高多了。
6.2 使用 nmcli 修改而不重启网卡
以前改 IP 的老套路是 vi ifcfg-eth0 然后 systemctl restart network,每次都要担心断连。用 nmcli 之后可以彻底告别这种状态。改配置和激活分两步,配合脚本可以做到比较平滑的切换。例如把 IP 改成新网段的命令:
nmcli connection modify eno1 ipv4.addresses 10.0.0.10/24 ipv4.gateway 10.0.0.1 ipv4.method manual nmcli connection up eno1注意,如果你的机器是通过这个 IP 远程连接的,执行 up 瞬间网络会中断,然后再恢复。为了避免把自己断出去,建议先把新 IP 用 +ipv4.addresses 追加进去,等确认能连通后再把旧 IP 移除。这是我在生产环境切换 IP 时常用的技巧:
nmcli connection modify eno1 +ipv4.addresses 10.0.0.10/24 nmcli connection up eno1 ping 10.0.0.10 nmcli connection modify eno1 -ipv4.addresses 192.168.10.100/24 nmcli connection up eno1先加新地址,等新地址通了,再减掉旧地址。中间网络不会完全断开,远程操作安全性高很多。
6.3 配置文件的备份和恢复
虽然 nmcli 面向命令行,但底层还是要写配置文件的。要从一个环境复制网络配置到另一台机器,最省事的是直接拷贝 /etc/NetworkManager/system-connections/ 下对应的 nmconnection 文件。拷贝前先 nmcli connection show 查看有哪些连接,再 cp 文件,到新机器后执行 nmcli connection reload 加载。不过要注意文件权限,NetworkManager 要求连接文件权限通常是 600,属主 root,否则拒绝加载。我遇到过复制过去一切正常,但 NetworkManager 不认文件的情况,最后发现是权限变成了 644。
每次修改重要网络配置之前,我都会先把当前连接文件备份一下:
cp -a /etc/NetworkManager/system-connections/ /root/netbak-$(date +%F)这个习惯救过我两次,一次是 bond 配置损坏导致网卡起不来,另一次是 DNS 改成错误地址后网络全断。有备份在手,恢复网络就是一两分钟的事。
6.4 我最后想提醒的一件小事
别看 nmcli 的命令面面俱到,它也不是万能的。比如复杂的策略路由、多路由表规则,nmcli 支持不如直接写 ip rule / ip route 顺手。我的习惯是:普通网络配置用 nmcli,路由策略和高级 QoS 用 iproute2,两边不打架。最后分享一个检查习惯:每次配置完 bond 或者改完网卡,我都会先 nmcli general status 看整体状态,再 nmcli device status 看设备,最后 cat /proc/net/bonding/bond0 确认链路细节,三层检查全过才敢收工。刚开始你会觉得多条命令啰嗦,但等你碰到过几次半夜被报警电话叫起来排查网络的事,就会明白这种检查习惯能省下多少睡眠时间。