reinstall/fix-eth-name.sh
2025-01-10 00:43:26 +08:00

240 lines
7.1 KiB
Bash

#!/usr/bin/env bash
# shellcheck shell=dash
# shellcheck disable=SC3001,SC3010
# alpine 使用 busybox ash
set -eE
# 本脚本在首次进入新系统后运行
# 将 trans 阶段生成的网络配置中的网卡名(eth0) 改为正确的网卡名,也适用于以下情况
# 1. alpine 要运行此脚本,因为安装后的内核可能有 netboot 没有的驱动
# 2. dmit debian 普通内核(安装时)和云内核网卡名不一致
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=928923
# todo: 删除 cloud-init
to_lower() {
tr '[:upper:]' '[:lower:]'
}
retry() {
local max_try=$1
local interval=$2
shift 2
for i in $(seq "$max_try"); do
if "$@"; then
return
else
ret=$?
if [ "$i" -ge "$max_try" ]; then
return $ret
fi
sleep "$interval"
fi
done
}
# openeuler 本脚本运行一秒后才有 enp3s0
# 用 systemd-analyze plot >a.svg 发现 sys-subsystem-net-devices-enp3s0.device 也是出现在 NetworkManager 之后
# 因此需要等待网卡出现
get_ethx_by_mac() {
mac=$(echo "$1" | to_lower)
retry 10 0.5 _get_ethx_by_mac "$mac"
}
_get_ethx_by_mac() {
if true; then
# 过滤 azure vf (带 master ethx)
ip -o link | grep -i "$mac" | grep -v master | awk '{print $2}' | cut -d: -f1 | grep .
return
else
for i in $(cd /sys/class/net && echo *); do
if [ "$(cat "/sys/class/net/$i/address")" = "$mac" ]; then
echo "$i"
return
fi
done
return 1
fi
}
fix_rh_sysconfig() {
for file in /etc/sysconfig/network-scripts/ifcfg-eth*; do
# 没有 ifcfg-eth* 也会执行一次,因此要判断文件是否存在
[ -f "$file" ] || continue
mac=$(grep ^HWADDR= "$file" | cut -d= -f2 | grep .) || continue
ethx=$(get_ethx_by_mac "$mac") || continue
proper_file=/etc/sysconfig/network-scripts/ifcfg-$ethx
if [ "$file" != "$proper_file" ]; then
# 更改文件内容
sed -i "s/^DEVICE=.*/DEVICE=$ethx/" "$file"
# 不要直接更改文件名,因为可能覆盖已有文件
mv "$file" "$proper_file.tmp"
fi
done
# 更改文件名
for tmp_file in /etc/sysconfig/network-scripts/ifcfg-e*.tmp; do
if [ -f "$tmp_file" ]; then
mv "$tmp_file" "${tmp_file%.tmp}"
fi
done
}
fix_suse_sysconfig() {
for file in /etc/sysconfig/network/ifcfg-eth*; do
[ -f "$file" ] || continue
# 可能两边有引号
mac=$(grep ^LLADDR= "$file" | cut -d= -f2 | sed "s/'//g" | grep .) || continue
ethx=$(get_ethx_by_mac "$mac") || continue
old_ethx=${file##*-}
if ! [ "$old_ethx" = "$ethx" ]; then
# 不要直接更改文件名,因为可能覆盖已有文件
for type in ifcfg ifroute; do
old_file=/etc/sysconfig/network/$type-$old_ethx
new_file=/etc/sysconfig/network/$type-$ethx.tmp
# 防止没有 ifroute-eth* 导致中断脚本
if [ -f "$old_file" ]; then
mv "$old_file" "$new_file"
fi
done
fi
done
# 上面的循环结束后,再将 tmp 改成正式文件
for tmp_file in \
/etc/sysconfig/network/ifcfg-e*.tmp \
/etc/sysconfig/network/ifroute-e*.tmp; do
if [ -f "$tmp_file" ]; then
mv "$tmp_file" "${tmp_file%.tmp}"
fi
done
}
fix_network_manager() {
for file in /etc/NetworkManager/system-connections/cloud-init-eth*.nmconnection; do
[ -f "$file" ] || continue
mac=$(grep ^mac-address= "$file" | cut -d= -f2 | grep .) || continue
ethx=$(get_ethx_by_mac "$mac") || continue
proper_file=/etc/NetworkManager/system-connections/$ethx.nmconnection
# 更改文件内容
sed -i "s/^id=.*/id=$ethx/" "$file"
# 更改文件名
mv "$file" "$proper_file"
done
}
# auto lo
# iface lo inet loopback
# # mac 11:22:33:44:55:66 # 用此行匹配网卡
# auto eth0
# iface eth0 inet static
# address 1.1.1.1/25
# gateway 1.1.1.1
# dns-nameservers 1.1.1.1
# dns-nameservers 8.8.8.8
# iface eth0 inet6 static
# address 2602:1:0:80::100/64
# gateway 2602:1:0:80::1
# dns-nameserver 2606:4700:4700::1111
# dns-nameserver 2001:4860:4860::8888
fix_ifupdown() {
file=/etc/network/interfaces
tmp_file=$file.tmp
rm -f "$tmp_file"
if [ -f "$file" ]; then
while IFS= read -r line; do
del_this_line=false
if [[ "$line" = "# mac "* ]]; then
ethx=
if mac=$(echo "$line" | awk '{print $NF}'); then
ethx=$(get_ethx_by_mac "$mac") || true
fi
del_this_line=true
elif [[ "$line" = "iface e"* ]] ||
[[ "$line" = "auto e"* ]] ||
[[ "$line" = "allow-hotplug e"* ]]; then
if [ -n "$ethx" ]; then
line=$(echo "$line" | awk "{\$2=\"$ethx\"; print \$0}")
fi
fi
if ! $del_this_line; then
echo "$line" >>"$tmp_file"
fi
done <"$file"
mv "$tmp_file" "$file"
fi
}
fix_netplan() {
file=/etc/netplan/50-cloud-init.yaml
tmp_file=$file.tmp
rm -f "$tmp_file"
if [ -f "$file" ]; then
while IFS= read -r line; do
if echo "$line" | grep -Eq '^[[:space:]]+macaddress:'; then
# 得到正确的网卡名
mac=$(echo "$line" | awk '{print $NF}' | sed 's/"//g')
ethx=$(get_ethx_by_mac "$mac") || true
elif echo "$line" | grep -Eq '^[[:space:]]+eth[0-9]+:'; then
# 改成正确的网卡名
if [ -n "$ethx" ]; then
line=$(echo "$line" | sed -E "s/[^[:space:]]+/$ethx:/")
fi
fi
echo "$line" >>"$tmp_file"
# 删除 set-name 不过这一步在 trans 已完成
# 因为 netplan-generator 会在 systemd generator 阶段就根据 netplan 配置重命名网卡
# systemd generator 阶段比本脚本和 systemd-networkd 更早运行
# 倒序
done < <(grep -Ev "^[[:space:]]+set-name:" "$file" | tac)
# 再倒序回来
tac "$tmp_file" >"$file"
rm -f "$tmp_file"
# 通过 systemd netplan generator 生成 /run/systemd/network/10-netplan-enp3s0.network
systemctl daemon-reload
fi
}
fix_systemd_networkd() {
for file in /etc/systemd/network/10-cloud-init-eth*.network; do
[ -f "$file" ] || continue
mac=$(grep ^MACAddress= $file | cut -d= -f2 | grep .) || continue
ethx=$(get_ethx_by_mac "$mac") || continue
proper_file=/etc/systemd/network/10-$ethx.network
# 更改文件内容
sed -Ei "s/^Name=eth[0-9]+/Name=$ethx/" "$file"
# 更改文件名
mv "$file" "$proper_file"
done
}
fix_rh_sysconfig
fix_suse_sysconfig
fix_network_manager
fix_ifupdown
fix_netplan
fix_systemd_networkd