如何在Bash中用ip命令获取设备子网掩码并清零非掩码位?
如何在Bash中从网卡IP生成网段格式用于路由配置?
我来分享几个在Bash里实现这个需求的简便方案,都是日常写脚本时常用的思路:
方法一:用ipcalc工具(最直观易读)
很多Linux发行版默认自带ipcalc工具,它专门用来处理IP地址和子网相关的计算,能直接帮你提取网段:
# 第一步:获取网卡eno1的IPv4地址/CIDR格式 ip_cidr=$(ip -f inet -o addr show dev eno1 | awk '{print $4}') # 第二步:用ipcalc提取对应的网段 network_cidr=$(ipcalc -n "$ip_cidr" | awk -F'=' '{print $2}') # 第三步:添加路由 ip route add table 128 to "$network_cidr" dev eno1
ipcalc -n会输出类似NETWORK=192.168.1.0/24的结果,用awk拆分就能直接拿到我们需要的网段格式。如果你的系统没装ipcalc,可以用包管理器安装(比如apt install ipcalc或yum install ipcalc)。
方法二:纯Awk位运算实现(无需额外工具)
如果是最小化系统没有ipcalc,可以用Awk的位运算直接计算网段,完全不依赖外部工具:
ip -f inet -o addr show dev eno1 | awk -F'[ /]+' ' { # 拆分IP为四个字段,提取CIDR前缀 split($4, ip_parts, ".") prefix = $5 # 计算子网掩码的数值(32位无符号整数) mask = 0xffffffff << (32 - prefix) # 计算网段的每个部分 part1 = (ip_parts[1] << 24) & mask part2 = (ip_parts[2] << 16) & mask part3 = (ip_parts[3] << 8) & mask part4 = ip_parts[4] & mask # 拼接成标准的网段格式 network = sprintf("%d.%d.%d.%d/%d", part1 >> 24, part2 >> 16, part3 >> 8, part4, prefix) # 可以直接在这里执行路由命令,或者先输出验证 print network # system("ip route add table 128 to " network " dev eno1") }'
这个方法通过位运算把IP地址和子网掩码做按位与,直接得到网段的网络地址,适合环境受限的场景。
方法三:利用ip命令本身的路由信息(最简洁)
其实ip命令已经能直接获取网卡的直连网段,根本不需要自己计算:
# 直接提取eno1的直连网段 network_cidr=$(ip -f inet route show dev eno1 scope link | awk '{print $1}') # 添加路由 ip route add table 128 to "$network_cidr" dev eno1
ip route show dev eno1 scope link会输出网卡所在的直连网段(比如192.168.1.0/24),直接取第一个字段就是你要的格式。这个方法最省事,前提是网卡已经配置了正常的直连路由(一般正常配置的网卡都会有这条路由)。
个人最推荐方法三,因为它完全依赖系统自带的ip命令,步骤最少也最不容易出错。如果你的场景下方法三不适用,再考虑前两种方案。
内容的提问来源于stack exchange,提问作者user8370684




