在CentOS 7及以上版本中,ifconfig命令已经被官方标记为过时工具,取而代之的是ip命令。如果你的运维脚本里还在大量使用ifconfig来获取IP地址、子网掩码、MAC地址等网络信息,那么你必须尽快做脚本改造。核心思路就是:把所有调用ifconfig的地方替换成对应的ip命令参数,同时注意输出格式的变化,因为ip命令的输出是人类可读的纯文本,不像ifconfig那样有固定的字段分隔模式,所以解析方式也要跟着调整。

先说最常见的场景:获取本机IP地址。原来ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | cut -d: -f2 这种写法,现在要改成 ip addr show eth0 | grep 'inet ' | awk '{print $2}' | cut -d/ -f1。注意几个细节:ip命令里网络接口名可能是ens33、enp0s3这种新命名方式,不再是eth0;inet后面跟的是CIDR格式的地址加掩码,所以分隔符从冒号变成了斜杠。

为什么CentOS要废弃ifconfig

ifconfig属于net-tools工具包,这个包从2001年之后就几乎没有更新过了。它不支持很多现代网络特性,比如多IP绑定、VLAN、隧道接口的精细管理。而ip命令属于iproute2工具包,是Linux内核网络子系统的官方维护工具,功能全面且持续更新。CentOS 7开始默认不再预装net-tools,你得手动yum install net-tools才能用ifconfig,但这只是临时方案,长远来看必须迁移。

常用ifconfig到ip命令的对照表

做脚本改造之前,先把常用操作列出来,心里有个底:

ifconfig eth0                    →  ip addr show eth0
ifconfig eth0 up                 →  ip link set eth0 up
ifconfig eth0 down               →  ip link set eth0 down
ifconfig eth0 192.168.1.100      →  ip addr add 192.168.1.100/24 dev eth0
ifconfig eth0 netmask 255.255.255.0 → ip addr add 192.168.1.100/24 dev eth0
ifconfig eth0 mtu 1500           →  ip link set eth0 mtu 1500
ifconfig eth0 hw ether 00:11:22:33:44:55 → ip link set eth0 address 00:11:22:33:44:55
route -n                         →  ip route show
route add default gw 192.168.1.1  →  ip route add default via 192.168.1.1
netstat -i                       →  ip -s link show
netstat -r                       →  ip route show
arp -a                           →  ip neigh show
脚本改造的核心步骤和实操方法

改造脚本不是简单的全局替换,因为输出格式完全不同。你需要分三步走:第一步,扫描脚本中所有ifconfig、route、netstat、arp的调用;第二步,逐个替换成对应的ip命令;第三步,调整awk、sed、grep的解析逻辑。

举个实际例子,假设你有一个部署脚本,里面有这么一段用来获取网关地址:

GATEWAY=$(ifconfig eth0 | grep 'inet addr' | awk '{print $3}' | cut -d: -f1)

这段代码本身逻辑就有问题,因为ifconfig输出的inet addr行第三列其实是Bcast广播地址,不是网关。但不管怎样,改成ip命令后正确写法应该是:

GATEWAY=$(ip route show | grep default | awk '{print $3}')

如果你的脚本需要获取所有网络接口的IP列表,原来可能这么写:

for iface in $(ifconfig -s | awk '{print $1}'); do
    ip=$(ifconfig $iface | grep 'inet addr' | awk '{print $2}' | cut -d: -f2)
    echo "$iface: $ip"
done

改造后应该写成:

for iface in $(ip -o link show | awk -F': ' '{print $2}'); do
    ip=$(ip -4 addr show dev $iface | grep 'inet ' | awk '{print $2}' | cut -d/ -f1)
    echo "$iface: $ip"
done

这里用了ip -o link show,输出格式是一行一个接口,方便解析。ip -4限定只看IPv4地址,避免混进IPv6的信息。

处理接口命名变化的问题

CentOS 7以上用的是可预测网络接口命名,接口名不再是eth0、eth1,而是像ens33、enp0s3、ens192这种。你的脚本如果硬编码了eth0,那在新机器上肯定跑不通。解决办法有两种:一种是在脚本开头动态获取第一个活动接口,另一种是通过MAC地址或PCI地址来定位接口。

# 方法一:获取第一个UP状态的接口
PRIMARY_IFACE=$(ip -o link show | awk -F': ' '$3=="UP"{print $2; exit}')

# 方法二:通过MAC地址查找接口名
MAC="00:11:22:33:44:55"
IFACE=$(ip link show | grep -B1 "$MAC" | head -1 | awk -F': ' '{print $2}' | tr -d ' ')
获取MAC地址的方式变化

原来ifconfig eth0输出里直接有HWaddr字段,现在ip命令要用ip link show eth0,然后从link/ether后面提取。写成脚本片段:

MAC=$(ip link show dev $PRIMARY_IFACE | grep 'link/ether' | awk '{print $2}')

如果你需要批量获取所有接口的MAC,可以用:

ip -o link show | awk -F'link/ether ' '{print $2}' | awk '{print $1}'
DNS和路由相关的改造

很多运维脚本会读取/etc/resolv.conf来获取DNS服务器,这部分其实不受ifconfig废弃的影响。但如果脚本里用了route命令来操作路由表,就需要改成ip route。比如原来添加静态路由:

route add -net 10.0.0.0/24 gw 192.168.1.1

改成:

ip route add 10.0.0.0/24 via 192.168.1.1

删除路由也类似:route del改成ip route del。查看路由表用ip route show代替route -n,输出格式更清晰,每行一个路由条目。

批量改造脚本的自动化技巧

如果你维护着几十台服务器,每台上面都有老脚本要改,手动一台台改太慢。可以写一个sed替换脚本来批量处理。但要注意,sed替换只能处理简单的模式,复杂逻辑还是得人工检查。一个基础的替换脚本示例:

#!/bin/bash
# 批量替换脚本中的ifconfig为ip命令
for script in /opt/scripts/*.sh; do
    cp "$script" "$script.bak"
    sed -i 's/ifconfig \([a-z0-9]*\)/ip addr show \1/g' "$script"
    sed -i 's/ifconfig \([a-z0-9]*\) up/ip link set \1 up/g' "$script"
    sed -i 's/ifconfig \([a-z0-9]*\) down/ip link set \1 down/g' "$script"
    sed -i 's/ifconfig \([a-z0-9]*\) hw ether/ip link set \1 address/g' "$script"
    sed -i 's/ifconfig \([a-z0-9]*\) mtu/ip link set \1 mtu/g' "$script"
    sed -i 's/route add default gw/ip route add default via/g' "$script"
    sed -i 's/route del/ip route del/g' "$script"
    sed -i 's/route -n/ip route show/g' "$script"
    sed -i 's/netstat -i/ip -s link show/g' "$script"
    sed -i 's/netstat -r/ip route show/g' "$script"
    sed -i 's/arp -a/ip neigh show/g' "$script"
done

这个脚本做了基础替换,但替换后你必须逐台验证,因为sed不理解上下文,可能产生错误替换。特别是ifconfig后面跟参数的情况,有些参数含义在ip命令里完全不同,比如netmask参数在ip命令里不存在,需要改成CIDR写法。

改造后的测试验证要点

脚本改完不是就完事了,必须在测试环境跑一遍。重点验证这几项:第一,能否正确获取到IP地址,特别是多网卡环境下是否拿到了预期的那个接口IP;第二,网关和DNS配置是否正确读取;第三,网络接口的启停操作是否正常;第四,MAC地址获取是否准确。建议在测试时加上调试输出,把ip命令的原始输出打印出来对比一下。

# 调试用:打印ip命令原始输出
echo "=== 接口信息 ==="
ip -o addr show
echo "=== 路由表 ==="
ip route show
echo "=== 邻居表 ==="
ip neigh show
一些容易踩的坑

第一个坑:ip命令输出中inet后面可能带scope global或者scope link,awk解析时如果不注意会把scope当成IP的一部分。解决办法是用cut -d/ -f1先把CIDR切掉,再取第一列。第二个坑:有些老脚本用ifconfig的输出判断接口是否存在,比如ifconfig eth0 2>/dev/null然后判断返回值。ip命令在接口不存在时也会报错,但错误信息不同,需要调整判断逻辑。第三个坑:CentOS 6和CentOS 7的网络配置文件位置不同,/etc/sysconfig/network-scripts/ifcfg-eth0在新版本里可能变成ifcfg-ens33,脚本里如果有对配置文件的操作也要同步改。

长期建议:逐步用Ansible等工具管理

如果你的运维工作还停留在手动改脚本的阶段,建议借这次改造的机会,把网络配置纳入Ansible或类似的自动化运维工具管理。用ip命令写成标准化的playbook或role,以后新机器部署直接跑自动化脚本,不用再担心ifconfig过时的问题。ip命令的输出虽然不如ifconfig规整,但配合json输出格式(ip -j addr show)可以得到结构化数据,更适合程序解析。

总结一下,CentOS运维中用ip命令替代ifconfig的脚本改造,本质上就是三件事:命令替换、格式适配、逻辑校验。命令替换有对照表可以查,格式适配需要根据ip的输出重新写解析逻辑,逻辑校验需要在测试环境充分验证。这个改造不复杂,但细节多,耐心做完之后你的脚本就能在CentOS 7、8、9甚至未来的版本上长期稳定运行。