Administrator
发布于 2026-01-07 / 4 阅读
0
0

Debian12 网卡批量dhcp设置

#!/usr/bin/env bash
set -euo pipefail

if [ "${EUID:-$(id -u)}" -ne 0 ]; then
  echo "需要以 root 权限运行"
  exit 1
fi

detect_manager() {
  if command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager; then
    echo "nm"; return
  fi
  if systemctl is-enabled --quiet systemd-networkd || [ -d /etc/systemd/network ]; then
    echo "networkd"; return
  fi
  if [ -f /etc/network/interfaces ] || [ -d /etc/network/interfaces.d ]; then
    echo "ifupdown"; return
  fi
  echo "unknown"
}

list_ifaces() {
  ip -o link show | awk -F': ' '{print $2}' \
    | awk '!/^lo$/ && !/^docker/ && !/^br/ && !/^veth/ && !/^vmnet/ && !/^tailscale/ && !/^zt/ && !/^wg/ && !/^tap/ && !/^tun/ {print}'
}

iface_defined_in_ifupdown() {
  local iface="$1"
  grep -Rqs "iface[[:space:]]\+$iface[[:space:]]\+inet" /etc/network/interfaces /etc/network/interfaces.d 2>/dev/null
}

nm_apply_dhcp() {
  local iface="$1"
  local conns
  conns=$(nmcli -t -f NAME,DEVICE connection show | awk -F: -v d="$iface" '$2==d{print $1}')
  if [ -z "$conns" ]; then
    echo "NetworkManager:未找到绑定到 ${iface} 的连接"
    return
  fi
  echo "NetworkManager:切换 ${iface} 到 DHCP"
  while IFS= read -r c; do
    nmcli connection modify "$c" ipv4.method auto ipv4.addresses "" ipv4.gateway "" ipv4.dns "" ipv4.never-default no connection.autoconnect yes
    nmcli connection down "$c" || true
    nmcli connection up "$c"
  done <<< "$conns"
}

networkd_write_unit_minimal() {
  local iface="$1"
  local out="/etc/systemd/network/99-dhcp-${iface}.network"
  install -m 0644 /dev/null "$out"
  {
    echo "[Match]"
    echo "Name=${iface}"
    echo "[Network]"
    echo "DHCP=yes"
  } > "$out"
  if ! systemd-analyze verify "$out" >/dev/null 2>&1; then
    rm -f "$out"
    return 1
  fi
  echo "systemd-networkd:为 ${iface} 写入 DHCP 覆盖 ${out}"
  return 0
}

networkd_reload_once() {
  systemctl daemon-reload
  if systemctl is-active --quiet systemd-networkd; then
    systemctl reload systemd-networkd || systemctl restart systemd-networkd
  else
    systemctl reset-failed systemd-networkd || true
    systemctl start systemd-networkd
  fi
}

ifupdown_apply_dhcp_file() {
  local file="$1"; shift
  local targets_csv="$*"
  [ -f "$file" ] || return 0
  local bak="${file}.bak-$(date +%F-%H%M%S)"
  cp -a "$file" "$bak"
  echo "ifupdown:备份 ${file} -> ${bak} 并切换为 DHCP"
  awk -v targets="$targets_csv" '
    BEGIN{ split(targets, tarr, " "); for(i in tarr){ target[tarr[i]]=1 } skip=0 }
    {
      if ($1=="iface" && target[$2] && $4=="static") { print $1, $2, $3, "dhcp"; skip=1; next }
      if (skip==1) {
        if ($1=="iface") { skip=0 }
        else if ($1 ~ /^(address|netmask|gateway|dns-nameservers)$/) { next }
      }
      print
    }
  ' "$bak" > "${file}.new"
  mv "${file}.new" "$file"
}

ifupdown_apply_dhcp() {
  local iface="$1"
  ifupdown_apply_dhcp_file "/etc/network/interfaces" "$iface"
  for f in /etc/network/interfaces.d/*; do
    [ -e "$f" ] && ifupdown_apply_dhcp_file "$f" "$iface"
  done
  ifdown "$iface" || true
  ifup "$iface" || true
  echo "ifupdown:${iface} 切换为 DHCP 完成"
}

main() {
  local manager; manager=$(detect_manager)
  if [ "$manager" = "unknown" ]; then
    echo "无法检测网络管理方式"; exit 1
  fi
  echo "检测到网络管理方式:$manager"

  local ifaces=("$@")
  if [ "${#ifaces[@]}" -eq 0 ]; then
    mapfile -t ifaces < <(list_ifaces)
  fi
  if [ "${#ifaces[@]}" -eq 0 ]; then
    echo "未发现可操作网口"; exit 1
  fi

  local ok=(); local failed=()

  case "$manager" in
    nm)
      for iface in "${ifaces[@]}"; do nm_apply_dhcp "$iface" || failed+=("$iface"); done
      ok=("${ifaces[@]}")
      ;;
    networkd)
      for iface in "${ifaces[@]}"; do
        if iface_defined_in_ifupdown "$iface"; then
          ifupdown_apply_dhcp "$iface" && ok+=("$iface") || failed+=("$iface")
          continue
        fi
        if networkd_write_unit_minimal "$iface"; then
          ok+=("$iface")
        else
          echo "systemd-networkd:验证失败,尝试以 ifupdown 回退 ${iface}"
          if ifupdown_apply_dhcp "$iface"; then
            ok+=("$iface")
          else
            failed+=("$iface")
          fi
        fi
      done
      if [ "${#ok[@]}" -gt 0 ]; then
        networkd_reload_once || true
        for iface in "${ok[@]}"; do networkctl reconfigure "$iface" || networkctl up "$iface" || true; done
      fi
      ;;
    ifupdown)
      for iface in "${ifaces[@]}"; do if ifupdown_apply_dhcp "$iface"; then ok+=("$iface"); else failed+=("$iface"); fi; done
      ;;
  esac

  if [ "${#ok[@]}" -gt 0 ]; then
    echo "成功切换为 DHCP 的网口:${ok[*]}"
  fi
  if [ "${#failed[@]}" -gt 0 ]; then
    echo "失败的网口:${failed[*]}"
    exit 1
  fi
}

main "$@"


评论