脚本实现快速创建网络聚合,适用于 networkmanager 管理的网络※
#!/bin/bash
# 定义颜色变量
RED='\E[1;31m' # 红
GREEN='\E[1;32m' # 绿
YELLOW='\E[1;33m' # 黄
BLUE='\E[1;34m' # 蓝
PINK='\E[1;35m' # 粉红
SHANGREEN='\E[32;5m' # 绿色闪烁警示
SHANBLUE='\E[34;5m' # 蓝闪烁警示
RES='\E[0m' # 清除颜色ip检查※
check_ip() {
local IP=$1
if echo "$IP" | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null ; then
local octet1=$(echo "$IP" | awk -F. '{print $1}')
local octet2=$(echo "$IP" | awk -F. '{print $2}')
local octet3=$(echo "$IP" | awk -F. '{print $3}')
local octet4=$(echo "$IP" | awk -F. '{print $4}')
if (( octet1 >= 0 && octet1 <= 255 )) && \
(( octet2 >= 0 && octet2 <= 255 )) && \
(( octet3 >= 0 && octet3 <= 255 )) && \
(( octet4 >= 0 && octet4 <= 255 )); then
echo "IP $IP ok!"
return 0
else
echo "IP $IP not available (octet out of range)!"
return 1
fi
else
echo "IP 格式错误!"
return 1
fi
}数字转换为8位二进制数字,不足前补0※
D2B_PADDED()
{
local num="$1"
local d2b=$(echo "obase=2;$num" | bc)
printf "%08d" "$d2b" # 不加换行符,方便拼接
}验证掩码的正确性 (兼容CIDR和点分十进制)※
check_mask_format()
{
local mask_input="$1"
# 1. 检查是否是CIDR前缀 (0-32之间的数字)
if [[ "$mask_input" =~ ^([0-9]|[12][0-9]|3[0-2])$ ]]; then
# 确保是有效的数字范围
if (( mask_input >= 0 && mask_input <= 32 )); then
return 0 # 有效的CIDR前缀
fi
fi
# 2. 如果不是CIDR,检查是否是点分十进制格式
echo "$mask_input" | grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" > /dev/null
if [ $? -ne 0 ]; then # 如果不是点分十进制格式
return 1 # 无效格式
fi
# 3. 如果是点分十进制,检查八位字节值范围和连续的1/0模式
local octet1=$(echo "$mask_input" | awk -F. '{print $1}')
local octet2=$(echo "$mask_input" | awk -F. '{print $2}')
local octet3=$(echo "$mask_input" | awk -F. '{print $3}')
local octet4=$(echo "$mask_input" | awk -F. '{print $4}')
# 检查每个八位字节是否在0到255之间
if ! (( octet1 >= 0 && octet1 <= 255 )) || \
! (( octet2 >= 0 && octet2 <= 255 )) || \
! (( octet3 >= 0 && octet3 <= 255 )) || \
! (( octet4 >= 0 && octet4 <= 255 )); then
return 2 # 八位字节超出范围
fi
local bin_mask=""
bin_mask+=$(D2B_PADDED "$octet1")
bin_mask+=$(D2B_PADDED "$octet2")
bin_mask+=$(D2B_PADDED "$octet3")
bin_mask+=$(D2B_PADDED "$octet4")
# 检查是否是连续的1后面跟着连续的0 (标准子网掩码特征)
if [[ "$bin_mask" =~ ^1*0*$ ]]; then
return 0 # 有效的点分十进制掩码
else
return 3 # 无效的掩码模式 (例如: 255.255.255.1)
fi
}掩码转换 (统一转换为CIDR前缀长度)※
mask2cdr ()
{
local mask_input="$1"
local masknum=0
# 1. 如果输入已经是CIDR前缀 (0-32之间的数字)
if [[ "$mask_input" =~ ^([0-9]|[12][0-9]|3[0-2])$ ]]; then
echo "$mask_input" # 直接输出该数字
return 0
fi
# 2. 如果是点分十进制,转换为32位二进制并计算前导1的个数
local octet1=$(echo "$mask_input" | awk -F. '{print $1}')
local octet2=$(echo "$mask_input" | awk -F. '{print $2}')
local octet3=$(echo "$mask_input" | awk -F. '{print $3}')
local octet4=$(echo "$mask_input" | awk -F. '{print $4}')
local bin_mask=""
bin_mask+=$(D2B_PADDED "$octet1")
bin_mask+=$(D2B_PADDED "$octet2")
bin_mask+=$(D2B_PADDED "$octet3")
bin_mask+=$(D2B_PADDED "$octet4")
# 计算前导'1'的个数
masknum=$(echo "$bin_mask" | grep -o "1" | wc -l)
echo "$masknum" # 输出计算出的CIDR前缀长度
return 0
}删除之前bond※
nmcli connection delete bond01 &>/dev/null
nmcli connection delete bond0 &>/dev/null
array=(`nmcli -f DEVICE device | grep -v DEVICE|grep -v virbr0 |grep -v lo |grep -v bond`)
NUM=${#array[@]}
NUM=`expr $NUM - 1`
for i in $(seq 0 $NUM)
do
temp=${array[$i]}
nmcli connection delete bond0-slave-$temp &>/dev/null
done
nmcli connection show
设置bond0接口※
echo -e "${GREEN}设置bond0接口,模式0${RES}"
nmcli connection add type bond con-name bond01 ifname bond0 mode 0
#设置bond0的IP
echo -e "${GREEN}设置bond0的IP${RES}"
printf "输入聚合网口bond0的第一个ip:\n"
while true ; do
read -p "输入ip: " bondIP
check_ip "$bondIP"
[ $? -eq 0 ] && break
done
while true ; do
read -p "输入子网掩码 (例如: 255.255.255.0 或 24): " bondmask
check_mask_format "$bondmask"
if [ $? -eq 0 ]; then
break
else
echo -e "${RED}子网掩码格式或值不正确,请重新输入。${RES}"
fi
done
# 捕获mask2cdr的输出作为CIDR前缀
mask_prefix=$(mask2cdr "$bondmask")
ipandmask="$bondIP/$mask_prefix"
echo "设置的IP地址和掩码为: $ipandmask"
nmcli connection modify bond01 ipv4.addresses "$ipandmask"
while :
do
printf "是否设置其他IP,是输入y,否n:"
read otherIP
if [ "y" = "$otherIP" ]; then
printf "输入聚合网口bond0的其他ip:\n"
while true ; do
read -p "输入ip: " bondIP
check_ip "$bondIP"
[ $? -eq 0 ] && break
done
while true ; do
read -p "输入子网掩码 (例如: 255.255.255.0 或 24): " bondmask
check_mask_format "$bondmask"
if [ $? -eq 0 ]; then
break
else
echo -e "${RED}子网掩码格式或值不正确,请重新输入。${RES}"
fi
done
# 捕获mask2cdr的输出作为CIDR前缀
mask_prefix=$(mask2cdr "$bondmask")
ipandmask="$bondIP/$mask_prefix"
echo "添加的IP地址和掩码为: $ipandmask"
nmcli connection modify bond01 +ipv4.addresses "$ipandmask"
elif [ "n" = "$otherIP" ]; then
break
else
echo -e "${YELLOW}输入错误,请输入 'y' 或 'n'。${RES}"
fi
done
#设置IP 为手动模式
nmcli connection modify bond01 ipv4.method manual
#关闭ipv6
nmcli connection modify bond01 ipv6.method "disabled"将需要聚合的接口加入bond0※
printf "当前外网接口为:\n"
route -n | grep UG | awk '{print $8}'
echo "当前所有网络接口:"
array=(`nmcli -f DEVICE device | grep -v DEVICE|grep -v virbr0 |grep -v lo |grep -v bond`)
NUM=${#array[@]}
NUM=`expr $NUM - 1`
for i in $(seq 0 $NUM)
do
temp=${array[$i]}
echo "$i:$temp"
done
while :
do
printf "输入需要加入的一个接口序号,选择完毕输入n:"
read devicenum
if [ "n" = "$devicenum" ]; then
break
fi
# 检查输入是否为数字
if ! [[ "$devicenum" =~ ^[0-9]+$ ]]; then
echo -e "${RED}输入错误,请输入数字序号或 'n'。${RES}"
continue
fi
if [ "$devicenum" -gt "$NUM" ]; then
echo -e "${RED}序号错误,重新输入${RES}"
continue
fi
device=${array[$devicenum]}
echo "将接口 $device 加入 bond0-slave-$device"
# 获取 UUID
uuid=$(nmcli -t -f DEVICE,UUID c show | grep "^$device:" | cut -d':' -f2)
# 检查 UUID 是否存在并断开
if [ -n "$uuid" ]; then
echo "正在断开 $device (UUID: $uuid)..."
nmcli c down "$uuid" &>/dev/null
nmcli connection modify "$uuid" connection.autoconnect no &>/dev/null
else
echo "未找到 $device 的连接。"
fi
nmcli connection add type bond-slave con-name bond0-slave-$device ifname "$device" master bond01
done启用bond0聚合接口※
echo -e "${GREEN}启用bond0聚合接口${RES}"
nmcli connection up bond01
echo -e "${GREEN}bond0接口信息${RES}"
nmcli connection show
sleep 3
ip addr show bond0
echo -e "${GREEN}bond0接口速度${RES}"
sleep 5
ethtool bond0 |grep Speed
如果显示unknown 的速率,检查聚合的网口是否都启动了,如果没有启动尝试手动启动
nmcli connection up bond0-slave-$device
完整脚本下载※
https://yuyujing.cn/data/sh/centos8-bond0-fastcreate.sh