在CentOS 7上改网卡IP,很多人还停留在老套路:vim /etc/sysconfig/network-scripts/ifcfg-eth0,改完再service network restart。到了CentOS 8/9、Rocky Linux、Ubuntu Server 18.04往后,这套流程经常直接卡住——network服务没了,真正的网络管家是NetworkManager。而NetworkManager的命令行入口,就是nmcli。这篇博文不打算把man手册翻译一遍,而是从运维和项目实战的角度,把nmcli最常用的连接管理、设备查看、配置持久化、排障和bond/vlan等高阶场景一一拆开,解释每个命令为什么这么写、踩过什么坑。适合刚接触Linux网络管理的初学者,也适合那些还在用ifcfg文件配网卡、想彻底切换到nmcli的老手。
1. 先搞清楚nmcli管理的对象:连接、设备和NetworkManager
1.1 NetworkManager是什么,为什么现在的发行版都默认用它
NetworkManager不是一句简单的命令行工具,它本身是一个常驻后台的系统守护进程。以前Linux管理员习惯直接改ifcfg文件再重启network服务,靠的是一堆静态脚本;而NetworkManager是事件驱动的,它会做设备插拔检测、WiFi信号扫描、网络自动切换这些事,然后把网络状态以“连接”为单位统一管理。很多服务器管理员觉得NM多余,但它在多网卡、动态网络、桌面和虚拟化场景下其实比手工脚本稳定得多,这也是各大发行版默认启用它的原因。
在RHEL 7时代,network.service和NetworkManager还能共存,很多脚本还在兼容老写法;到了RHEL 8/9,network-scripts被直接移除,/etc/sysconfig/network-scripts/ifcfg-*只剩下一堆遗留注释文件,真正生效的网络配置全部由NetworkManager接管。这时候如果你还不会用nmcli,等于在服务器上少了一条胳膊。nmcli就是NetworkManager的命令行前端,它把所有网络管理功能都封装成了结构化命令,想查网卡、改IP、配bond,都用同一套语法完成。
1.2 connection(连接)和device(设备)到底是不是一回事
这是新手最容易蒙的地方。设备(device)是看得见摸得着的物理网卡,比如ens33、ens34、eth0;连接(connection)是“一张网卡上保存的一套网络配置”,包括IP、网关、DNS、是否DHCP、是否自动连接这些参数。可以拿手机理解:设备是手机本身,连接是SIM卡套餐。手机可以存多张SIM卡的信息,但同一时间只能有一张卡在提供通话流量;网卡也一样,可以配置多个连接,但同一时刻只会激活其中一个。
比如一张网卡ens33上,你可以建一个company连接用静态IP访问办公网,再建一个home连接用DHCP自动获取地址。到了公司执行nmcli connection up company,回家执行nmcli connection up home。两个连接共用同一张物理网卡,但遵循完全不同的配置。很多人在这一步没绕过来,后面看nmcli connection show的输出就特别容易迷茫。
1.3 热搜问题的正面回答:nmcli connection 到底能不能查看网卡
有个热搜问题叫“nmcli connection 是否能够查看下网卡”,这里直接给出答案:nmcli connection show列出的是系统里所有连接配置文件,不是物理网卡列表。它输出的NAME、UUID、TYPE、DEVICE四列中,TYPE表示连接类型,DEVICE列显示这个连接绑定在哪张网卡上,所以它能间接反映网卡与连接的对应关系;但如果你想看“当前有几张物理网卡、每张网的链路状态”,应该用nmcli device status。
bash复制# 查看连接配置,注意DEVICE列不等于网卡列表
nmcli connection show
NAME UUID TYPE DEVICE
company xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ethernet ens33
home xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ethernet ens33
virbr0 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx bridge virbr0
# 查看物理网卡及托管状态
nmcli device status
DEVICE TYPE STATE CONNECTION
ens33 ethernet connected company
ens34 ethernet disconnected --
看到区别了吗?connection show回答的是“系统里有哪些配置方案”,device status回答的是“物理上有哪些网卡、现在什么状态”。实际排查问题时,两条命令通常要配合使用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 查看类命令:从device status到connection show的实操对照
2.1 查看类命令的分工表
nmcli的查看命令最常用的是下面这组,我平时排查网络问题基本就靠它们。每个命令的侧重点不一样,选对了能省一半时间。
| 命令 | 用途 | 典型场景 |
|---|---|---|
| nmcli general status | 查看NetworkManager整体运行状态和主机名 | 判断NM是否正常运行 |
| nmcli device status | 列出所有网卡及状态 | 看服务器有几张网卡、是否被托管 |
| nmcli device show [网卡名] | 查看指定网卡的详细配置 | 查IP、网关、DNS、MAC、链路速率 |
| nmcli connection show | 列出所有连接配置 | 看有哪些配置文件、绑定关系 |
| nmcli connection show --active | 只看正在生效的连接 | 快速定位当前用的是哪套配置 |
| nmcli connection show <连接名> | 查看某个连接的详细参数 | 排查具体配置项 |
在实际操作中,我最常用的组合是“device status打前站、device show看细节、connection show --active确认当前配置”。比如一台新接手的机器,先跑一遍nmcli device status,马上就知道机器上有哪几张网卡、有没有被NM托管;再跑nmcli device show ens33,IP、网关、DNS、MAC一目了然;如果想确认现在真正生效的是哪个连接,直接看--active输出。
2.2 字段过滤与脚本友好输出:-f、-t、-g 参数
如果只是在终端里敲命令,上面这些输出足够用了。但一旦涉及自动化脚本,比如采集服务器IP、批量巡检,就必须用nmcli的字段过滤功能。nmcli支持-f指定字段、-t去掉表格边框、-g直接取值,三个参数组合起来非常适合写shell脚本。
bash复制# 只看某个连接的IP地址
nmcli -f IP4.ADDRESS[1] connection show company
IP4.ADDRESS[1]: 192.168.10.100/24
# 直接取出IP值,不带任何表头,适合赋值给变量
nmcli -g IP4.ADDRESS[1] connection show company
192.168.10.100/24
# 脚本里常用写法
IP=$(nmcli -g IP4.ADDRESS[1] connection show company)
echo $IP
注意字段名大小写不能写错,IP4.ADDRESS里的4是大写,后面带方括号下标表示第几个地址。一个连接配置多个IP地址时,[1]是第一个,[2]是第二个,这点在批量场景非常实用。我写巡检脚本时经常先nmcli -t -f DEVICE,STATE device status拿到“网卡名+状态”的干净列表,再循环去取IP,比解析一大段表格输出靠谱得多。
2.3 快速判断网卡链路问题的组合技巧
服务器网络不通,可能的原因有很多:网线没插、IP没配、网关丢了、DNS不对。用nmcli可以快速缩小范围。第一步跑nmcli device status看STATE,如果网卡处于disconnected,基本就是物理链路或驱动问题;如果是connected但网络还是不通,再往下看细节。
bash复制# 查看网卡细节,重点关注链路状态和IP
nmcli device show ens33
GENERAL.STATE: 100 (connected)
GENERAL.CONNECTION: company
WIRED-PROPERTIES.CARRIER: on
IP4.ADDRESS[1]: 192.168.10.100/24
IP4.GATEWAY: 192.168.10.1
IP4.DNS[1]: 223.5.5.5
GENERAL.STATE显示100表示connected,WIRED-PROPERTIES.CARRIER的on/off直接反映网线有没有插好。如果CARRIER是off,别急着查IP配置,先检查物理线路。IP4.GATEWAY有没有值、IP4.DNS是不是预期配置,这些一眼就能扫完。整个过程不用切好几个工具,nmcli全包了。
3. 用nmcli完成网卡配置:add、modify、up的完整流程
3.1 从零配置一个静态IP连接
先说标准流程。假设现在要给ens33配置静态IP 192.168.10.100/24,网关192.168.10.1,DNS用223.5.5.5,连接名叫server-eth0。官方推荐的做法是先创建连接,再修改参数,最后激活,三步分开执行:
bash复制# 第一步:创建连接
nmcli connection add type ethernet con-name server-eth0 ifname ens33
# 第二步:修改静态IP、网关、DNS
nmcli connection modify server-eth0 \
ipv4.method manual \
ipv4.addresses 192.168.10.100/24 \
ipv4.gateway 192.168.10.1 \
ipv4.dns 223.5.5.5
# 第三步:激活连接
nmcli connection up server-eth0
这里的ipv4.method manual表示手工指定IP,如果写成auto就是DHCP。ipv4.addresses的写法必须是CIDR格式,192.168.10.100/24代表IP加掩码,别写成192.168.10.100 + netmask 255.255.255.0这种老格式,nmcli会直接报错。多个IP可以用引号包住空格分隔,比如ipv4.addresses "192.168.10.100/24 10.10.0.1/24",这在服务器上特别常用,一块网卡同时跑业务网和管理网。
3.2 配置与激活是两回事:为什么一定要up
我见过很多人执行完connection add和modify之后,发现IP没变,以为命令没生效。其实add和modify都只是操作“配置文件”,不会自动应用到设备上。连接配置文件就像一份改好的文档,你要把它真正加载到网卡上,必须执行nmcli connection up。up的机制是先把当前激活的连接停掉,再按新配置重新激活,所以执行完那一刻网络会闪断一下,SSH会话如果开着,会有明显卡顿。
有一个参数叫autoconnect,默认是yes。意思是NetworkManager服务启动时,会自动激活这个连接。如果你在服务器上新建了一个连接并写了autoconnect yes,那下次重启机器或重启NetworkManager服务时,它会自动生效;但当前这一刻,不手动up它就是不生效。所以排查问题时别只看配置文件对不对,还要确认连接有没有被激活,nmcli connection show --active看的就是这个。
3.3 修改、重命名、克隆和删除连接
配置交付之后经常会遇到调整需求,比如换个DNS、加个备用IP、把连接名改成更有业务含义的名字。这些操作都在modify里完成。
bash复制# 修改DNS(覆盖整个DNS列表)
nmcli connection modify server-eth0 ipv4.dns 114.114.114.114
# 追加一个备用DNS
nmcli connection modify server-eth0 +ipv4.dns 8.8.8.8
# 删除一个DNS
nmcli connection modify server-eth0 -ipv4.dns 8.8.8.8
# 重命名连接
nmcli connection modify server-eth0 connection.id server-prod
# 克隆连接
nmcli connection clone server-eth0 server-eth0-backup
# 删除连接
nmcli connection delete server-eth0
这里有个特别容易踩的坑:ipv4.dns、ipv4.addresses这类参数是列表型参数,单独执行modify时会“整体覆盖”而不是“追加”。如果原来DNS是223.5.5.5,你又执行一次modify ipv4.dns 8.8.8.8,结果是DNS变成8.8.8.8,223.5.5.5被挤掉了。想追加必须用+ipv4.dns的写法。重命名连接用的是connection.id属性,改完需要通过connection.filename确认文件是否也同步更名。克隆出来的连接会自动生成新UUID,不会和原连接冲突,适合做配置备份。
3.4 DHCP网卡上指定DNS的正确姿势
公司内网机器经常是DHCP获取IP,但DNS想用手工指定的公共DNS,不想要内网DNS。如果你只设置ipv4.dns,执行up之后发现生效的还是DHCP下发的DNS,那是因为还有另一个关键参数没动:ipv4.ignore-auto-dns。
bash复制# 保留DHCP获取IP,但DNS用手工指定的
nmcli connection modify server-eth0 \
ipv4.method auto \
ipv4.dns 223.5.5.5 \
ipv4.ignore-auto-dns yes
nmcli connection up server-eth0
ipv4.ignore-auto-dns yes的意思是忽略DHCP或路由通告自动下发的DNS,只用手工配置的DNS。这个参数在混合网络环境下几乎是必配的,不理解它的话,就会出现“明明设置了DNS,重启网卡后生效的却是内网DNS”这种迷惑行为。改完记得nmcli connection up让配置重新生效。
4. 配置写到哪了、重启丢不丢:nmcli的持久化机制与文件真相
4.1 连接配置文件的真实位置
很多人用nmcli配完网络后心里没底,总担心重启就丢。实际上nmcli创建的连接默认都会持久化到磁盘。在大多数现代发行版上,连接配置文件存放在/etc/NetworkManager/system-connections/目录下,一个连接对应一个conf文件,文件名就是连接名。比如上面创建的server-eth0,对应文件就是/etc/NetworkManager/system-connections/server-eth0.nmconnection。
在RHEL/CentOS系列上,如果系统配置了ifcfg-rh插件,NetworkManager还会同步维护/etc/sysconfig/network-scripts/ifcfg-*文件。怎么看某个连接到底存在哪个文件?执行下面这条命令:
bash复制nmcli -f connection.filename connection show server-eth0
connection.filename: /etc/NetworkManager/system-connections/server-eth0.nmconnection
这个字段直接告诉你当前连接配置的真实落盘位置,排查“配置在哪个文件”的问题时非常有用。看到路径在system-connections下,说明是标准的keyfile格式;看到路径在network-scripts下,说明走的是ifcfg兼容格式。两种格式都可以被NM读取,但不要手动交叉编辑,容易把NM搞晕。
4.2 为什么有时候修改完配置,重启就丢了
严格来讲,nmcli connection modify之后配置会立即写入磁盘,不会因为重启丢失。真正导致配置丢失或“看起来丢了”的通常有三种情况。
第一种,创建连接时用了--temp参数。nmcli connection add支持--temp,表示创建一个临时连接,只存在内存里,NM进程一退出或重启就没了。这种连接适合临时测试,不适合生产配置。第二种,有人直接用ip addr add给网卡加了IP,这种地址只存在于内核,NetworkManager完全不知道,重启必然丢失。第三种也是最常见的:手工编辑了配置文件,但没有执行nmcli connection reload,NM内存里的配置还是旧版本,看起来就像没改过。
判断一个连接是临时的还是持久的,看connection.mudname或文件是否存在就行。真正的持久化连接一定能在/run/NetworkManager/system-connections/或/etc/NetworkManager/system-connections/下找到对应文件,临时连接只在/run下且重启会清。
4.3 reload、restart、reapply三个操作的区别
这三个操作在生产环境里特别容易搞混,我专门拆开说。
nmcli connection reload:重新读取磁盘上的配置文件,让NM感知文件变化。它不会中断已经激活的连接,所以一般不会断网。修改了配置文件之后,用reload就够了。
systemctl restart NetworkManager:把整个NM进程重启,所有连接都会被重新扫描和激活。这个操作会闪断所有网络,SSH会话很可能直接断开。有些老教程动不动就让你重启NetworkManager服务,在远程服务器上这么做风险很高。
nmcli device reapply ens33:把当前激活的连接重新应用一次,让网卡按最新配置重新加载。它比restart轻量,比reload更彻底,适合修改连接参数后想让配置“立刻生效”的场景。
我的习惯是:改配置后先nmcli connection reload,再执行nmcli connection up让配置生效;如果只是调整了一些不影响连接的参数,用nmcli device reapply更保险。restart NetworkManager这种操作,除非物理进机房或者在控制台上,否则我一般不碰。
5. nmcli排障实战:unmanaged设备、DNS不生效、默认路由错乱
5.1 网卡显示unmanaged,NetworkManager根本不管这张卡
接手一台老服务器,跑nmcli device status,发现ens33的STATE是unmanaged,这就意味着这张网卡不在NetworkManager的管辖范围内,你执行connection up它也没反应。unmanaged的原因通常是:ifcfg文件里写了NM_CONTROLLED=no,或/etc/NetworkManager/NetworkManager.conf里配了unmanaged-devices,或者这张卡被systemd-networkd等其他网络服务接管了。
先看NetworkManager.conf里的相关配置:
bash复制cat /etc/NetworkManager/NetworkManager.conf
[main]
plugins=ifcfg-rh
# 如果有下面这行,说明指定网卡被排除管理
# unmanaged-devices=interface-name:ens33
如果确认是NM不托管,可以通过命令临时接管:
bash复制# 临时将ens33设为受NM管理
nmcli device set ens33 managed yes
但这只是运行时状态,重启后可能又变回unmanaged。要永久解决,要么把ifcfg文件里的NM_CONTROLLED改成yes,要么删掉NetworkManager.conf里的unmanaged-devices配置,然后systemctl reload NetworkManager。这里要提醒一句:如果机器上同时跑着systemd-networkd,它有可能会和NM抢网卡,最好先确认到底是谁在管,再决定动哪个服务。
5.2 DNS设置不生效的第一排查思路
DNS不生效是我在客户现场遇到最多的问题之一。执行了nmcli connection modify设置DNS,/etc/resolv.conf里的内容还是老样子,或者ping域名还是失败。先别急着重启网络服务,按这个顺序排查。
先看连接里DNS相关的参数到底有没有被正确记录:
bash复制nmcli connection show server-eth0 | grep -i dns
ipv4.dns: 223.5.5.5
ipv4.dns-search: --
ipv4.dns-options: --
ipv4.dns-priority: 0
ipv4.ignore-auto-dns: no
看到ipv4.ignore-auto-dns是no,而networking又是DHCP时,问题基本就锁定了。DHCP下发的DNS会覆盖手工配置,必须把ignore-auto-dns设为yes。还有一种情况是系统里跑了systemd-resolved,它在Ubuntu上是默认服务,会接管resolv.conf的写入,NM配置的DNS写不到/etc/resolv.conf里。这时候要么检查/etc/resolv.conf的软链接指向,要么确认systemd-resolved的配置。RHEL系列默认没这问题,但Ubuntu用户一定要警惕。
5.3 多网卡同时激活,出现两个默认路由
服务器上双网卡或多网卡很常见,但如果两块网卡的连接配置都写了网关,并且都处于激活状态,ip route里会出现两条default路由。内核会根据路由优先级选择出口,流量就可能走到你不想走的那张卡上,业务访问各种奇怪。
bash复制ip route
default via 192.168.10.1 dev ens33 proto static metric 100
default via 10.0.0.1 dev ens34 proto static metric 100
解决思路是明确哪张网卡是主出口,其他网卡只做业务流量或备份链路,不要声明默认网关。NM里有个专门参数控制这个行为:
bash复制# 让ens34上的连接不生成默认路由
nmcli connection modify server-eth0 ipv4.never-default yes
nmcli connection up server-eth0
ipv4.never-default设为yes后,这个连接即使配置了网关,也不会添加default路由。如果两张卡都确实需要网关但优先级要分主次,还可以用ipv4.route-metric调整路由优先级,数值越小优先级越高。多网卡环境下一定要控制好默认路由,不然后期排查网络问题会花掉几个小时。
5.4 SSH连接中改IP,如何避免把自己断在门外
这个问题我栽过一次,之后长记性了。远程SSH会话里执行nmcli connection up切换连接,如果新IP和当前IP不同,连接瞬间断开,而且如果新IP配置有误或网关不对,你就再也连不上服务器了。这时候再想改配置,只能去机房或带外管理口,非常被动。
几个实用经验:
- 远程修改前,先把新连接配置完整写好,反复确认IP、网关、掩码没有低级错误,再执行up。
- 如果服务器有两张网卡,留一张不变的网卡作为逃生通道,这样改另一张失败还能从逃生通道进去处理。
- 执行up之前先开一个tmux或screen会话,就算SSH断了,命令也会在会话里继续跑完,重新连上后能看到之前的输出。
- 条件允许的情况下,把network配置变更放在重启前做,重启后如果起不来还能从引导参数进入单用户模式排查。
总之,远程网络操作一定要有“断了之后还能怎么进去”的后手,这是运维的基本素养。
6. 生产环境实用玩法:bond、VLAN和主机名管理
6.1 用nmcli配置bond网卡
以前配bond要写一堆ifcfg文件,还要改bonding模块参数,非常繁琐。nmcli把bond配置压缩到了几步以内。假设要把ens33和ens34绑成一个bond0,模式用active-backup,IP配置为10.0.0.10/24:
bash复制# 创建一个bond连接
nmcli connection add type bond con-name bond0 ifname bond0 mode active-backup
# 创建两个子连接,分别把ens33和ens34绑定到bond0
nmcli connection add type ethernet con-name bond0-port1 ifname ens33 master bond0
nmcli connection add type ethernet con-name bond0-port2 ifname ens34 master bond0
# 给bond0配置IP
nmcli connection modify bond0 ipv4.method manual ipv4.addresses 10.0.0.10/24 ipv4.gateway 10.0.0.1
# 激活bond0
nmcli connection up bond0
bond mode支持active-backup(主备)、802.3ad(LACP,需要交换机配合)、balance-rr(轮询)等。服务器和高可用场景最常用的是active-backup,简单可靠;核心交换机支持LACP时用802.3ad可以获得带宽叠加和负载均衡。配置完成后,查看bond状态可以直接看内核虚拟文件:
bash复制cat /proc/net/bonding/bond0
如果看到Currently Active Slave字段和MII Status是up,说明bond工作正常。注意解除bond时,子连接和母连接都要删干净,nmcli connection delete bond0只删母连接,两个port连接还得单独删。
6.2 VLAN子接口配置
虚拟化/容器网络里经常需要在一张物理网卡上跑多个VLAN。nmcli创建VLAN子接口是一条命令的事:
bash复制# 在ens37上创建VLAN 100的子接口,命名为ens37.100
nmcli connection add type vlan con-name vlan100 ifname ens37.100 dev ens37 id 100 \
ipv4.method manual ipv4.addresses 192.168.100.1/24
nmcli connection up vlan100
这里的ifname是子接口在系统里的名称,dev是父接口,id是VLAN号。一条命令就把子接口和VLAN配置都建好了。之前手工配置VLAN要改父接口、子接口、路由表好几个文件,相比之下nmcli的体验好太多。如果子接口要跟bond搭配,把dev改成bond0就行。
6.3 用nmcli管理主机名
顺手提一个NM的功能:它不只管网卡,还管主机名。在RHEL/CentOS系里,nmcli general hostname可以查看和设置主机名:
bash复制# 查看当前主机名
nmcli general hostname
# 设置新主机名
nmcli general hostname web-prod-01
这个命令和hostnamectl set-hostname效果类似,但好处是如果DHCP或网络环境会动态改主机名,NM里能统一设置策略。虽然这不属于网卡配置,但在批量初始化服务器时经常和nmcli一起用,所以我放在这里提一句。
6.4 我的日常习惯:配置类用nmcli,排障类用ip命令
最后分享一点个人经验。我在日常工作中有一条比较清晰的边界:所有“需要长期生效”的网络配置,一律用nmcli完成;所有“临时看状态、临时加个IP做测试”的操作,用ip命令更快。nmcli的优势在于配置会持久化、有完整的连接管理概念,适合作为标准配置入口;ip命令类似于内核的直接操作窗口,重启即丢,但胜在即时和灵活。
还有一个习惯是给生产网络连接起名字时一定要有业务含义,不要直接用eth0这种系统名。比如web-prod-net、backup-link这种命名,后续维护和故障定位会省很多精力。配置完成后,用nmcli connection show --active核对一下当前生效状态,确认没有多出意外的默认路由或缺失网关,再离开操作台。这套流程跑顺之后,Linux网络配置基本不会再让你手忙脚乱。
