【shell脚本】Ubuntu 服务器实现自动配置网络

news/2025/1/9 1:39:52/文章来源:https://www.cnblogs.com/o-O-oO/p/18660866

在 Ubuntu 系统中,默认通过 Netplan 工具管理网络接口。通常我们只需要手动写好 /etc/netplan/ 目录下的 YAML 文件,一劳永逸地让系统在每次启动时应用相同配置。
然而,有些场景下可能需要一个脚本能:

  • 自动检测当前服务器是否已经是一个可用的静态 IP;如果网络畅通,就无需改动;
    
  • 如果网络不可用,则尝试对服务器所有网卡进行DHCP 获取 IP,并检测能否访问外网(例如 Ping 目标 IP 或域名);
    
  • 一旦找到能连通外网的网卡,就固定(静态)它当前的 IP/Gateway/DNS;
    
  • 如果所有网卡都无法获取可用网络,退出并提示失败。
    

类似逻辑多用于初次部署或自动化安装场景。
有以下风险需了解:

  • 如果只有单块网卡且依赖 SSH 远程,IP 变更后 SSH 会话极有可能断开;
    
  • 脚本会移除所有原先的 Netplan 文件后再写新的配置,过程里没有“netplan try”的回滚;
    
  • 如果脚本未能找出可用网卡并成功配置,系统最终会没有 Netplan 配置文件,需要人工从备份里恢复。
    

二、脚本逻辑概述

最终版本脚本(详见后文)包含以下步骤:

1、STEP A:判断是否已有可用静态网络

如果系统内没有任何网卡显示为“dynamic”,一般表示所有网卡要么是静态,要么未配置 IP。
脚本尝试 ping -c 3 baidu.com(或其他可达地址);若能联通,则说明已有可用的静态 IP 配置,脚本直接退出,不做改动。
如果 Ping 不通,则继续执行后续步骤。

2、STEP 0:备份并清空 Netplan 文件

将 /etc/netplan/.yaml 文件备份到 /var/backups/netplan-时间戳;
然后 rm -f /etc/netplan/
.yaml,保证后续生成的配置不与旧文件冲突。

3、STEP 1 ~ STEP 2:枚举所有网卡,检测/强制设置 DHCP

脚本列出除 lo 以外的所有网卡(ip link show),依次检查:
若成功,可马上把它转成静态配置;若失败(未分配到 IP,或无法通外网),就删掉临时文件,继续下一个网卡。
如果网卡已经是 “dynamic”(DHCP 模式),那么直接获取其当前 IP / 网关 / DNS,然后转为静态;
否则,脚本临时写入一个只含 dhcp4: yes 的 netplan 文件,netplan apply 后等待几秒,看能否成功分配 IP 并Ping 通目标。

4、STEP 3:将获取到的 IP 配置写回静态

用 ip -4 addr show dev NIC 拿到 IP(带 CIDR),ip route 拿到网关,/etc/resolv.conf 里拿到 DNS;
写进 /etc/netplan/99-auto-network.yaml,其中将 gateway4 替换为用 routes: 设置默认路由,并将 dhcp4 改为 no;
nameservers 部分默认会追加 8.8.8.8 和 114.114.114.114,如果只想用这两个,可把脚本里追加的逻辑改为覆盖;
netplan apply 使之生效,然后做一次 Ping 测试,观察连通性。

5、若所有网卡都尝试完仍失败

脚本会退出,并不会留下任何新的 netplan 文件;此时需要从前面备份的目录手动复制恢复。

三、常见注意事项

1、SSH 连接风险

如果脚本在改动当前使用的网卡 IP 段,SSH 会立刻断开,需要物理/带外或多网卡支持才能继续操作。

2、netplan apply 无回滚

脚本使用 netplan apply 而非 netplan try,一旦出现配置不通,将无法自动回退。

所以要么有冗余的访问方式,要么在测试环境充分验证。

3、DNS 逻辑

脚本默认将 DHCP 下发的 DNS 与 8.8.8.8、114.114.114.114 一起写入静态配置;

如果你只想保留那两个公共 DNS,请把相关代码改成直接覆盖。

4、DNS 或外网

脚本主要通过 ping baidu.com 判断外网连通。如果你所在网络访问百度不通,请改成 ping 114.114.114.114 或其他更适合的目标。

5、一次性或开机自启

大多数情况下,这种自动脚本用于一次性的网络初始化,不必在每次开机都重复执行;

如果确实要开机时自动跑,可做一个 systemd service 或放进 cron @reboot(但要注意网络依赖顺序)。

四、脚本示例

下文为最终整合的脚本示例:auto_dhcp_then_static.sh。
其中包含:

前置检查:如果没有网卡处于 DHCP(dynamic),且 ping 测试外网成功,说明已有可用静态网络,脚本立即退出。

否则,清空 netplan 文件并循环尝试各网卡:

    若网卡已是 DHCP,则转为静态;否则临时改为 DHCP,看能否上网;一旦成功,就“锁定”成静态 IP 并停止脚本。如果所有网卡都失败,则提示错误并退出。

请将其以 UTF-8 编码保存为 auto_dhcp_then_static.sh 并给予可执行权限:

#!/usr/bin/env bash
# -*- coding: utf-8 -*-
#
# auto_dhcp_then_static.sh
#
# 功能:
#   1) 如果当前已有可用静态网络(无dynamic网卡,且能ping外网),则直接退出
#   2) 否则备份并删除 /etc/netplan/*.yaml
#   3) 枚举所有网卡(excl. lo),若网卡是dynamic则直接转静态,否则强制DHCP测试
#   4) 找到能ping通外网的网卡后,将其固定IP
#   5) 若所有网卡都失败,退出不做最终保存
#
# 注意:
#   - netplan apply 无回滚,可能导致SSH断开
#   - 默认会追加 8.8.8.8、114.114.114.114 到 DNS
#   - ping目标默认为 baidu.com,请根据需要修改set -e  # 一旦出错立即退出CONFIG_FILE="/etc/netplan/99-auto-network.yaml"
PING_TARGET="baidu.com"  # 或换成 114.114.114.114###############################################################################
# STEP A:判断是否已有可用静态网络
###############################################################################
echo ">>> 检查是否已有可用的静态IP和网络连通..."HAS_DYNAMIC=false
ALL_NICS=$(ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$')
for nic in $ALL_NICS; doif ip -4 addr show dev "$nic" | grep -q "dynamic"; thenHAS_DYNAMIC=truebreakfi
done# 无dynamic网卡 -> 可能全是静态或没IP -> 测试能否ping通
if [ "$HAS_DYNAMIC" = false ]; thenecho "系统内未检测到dynamic网卡,可能已有静态IP或无IP。测试ping: $PING_TARGET"if ping -c 3 "$PING_TARGET" &> /dev/null; thenecho ">>> 当前网络已可达,视为静态网络可用,无需修改。退出。"exit 0elseecho ">>> 无法ping通,继续脚本流程..."fi
elseecho ">>> 存在dynamic网卡,可能需要转换,继续执行..."
fi###############################################################################
# STEP 0:备份并删除旧的 netplan 配置
###############################################################################
timestamp=$(date +%Y%m%d-%H%M%S)
backup_path="/var/backups/netplan-${timestamp}"echo ">>> 备份 /etc/netplan 到: $backup_path"
mkdir -p "$backup_path"
cp -r /etc/netplan/* "$backup_path"/ 2>/dev/null || true
echo ">>> 备份完成。"echo ">>> 删除现有 /etc/netplan/*.yaml"
rm -f /etc/netplan/*.yaml
echo ">>> 已删除旧的 netplan 文件。"
echo###############################################################################
# 列出非 lo 的网卡
###############################################################################
NICS=$(ip -o link show | awk -F': ' '{print $2}' | grep -v '^lo$')
if [[ -z "$NICS" ]]; thenecho "没有可用网卡(除lo外)!退出。"exit 0
fi###############################################################################
# 函数:尝试给网卡启用 DHCP 并测试连通
###############################################################################
try_dhcp_and_test() {local nic="$1"echo ">>> 对网卡 $nic 写入临时 DHCP 配置..."cat <<EOF > "$CONFIG_FILE"
network:version: 2renderer: networkdethernets:$nic:dhcp4: yes
EOFchmod 600 "$CONFIG_FILE"echo ">>> netplan apply (DHCP) on $nic..."netplan applyecho ">>> 等待5秒,让DHCP有机会拿到IP..."sleep 5local ip_cidrip_cidr=$(ip -4 addr show dev "$nic" | grep -oP '(?<=inet\s)\S+')if [[ -z "$ip_cidr" ]]; thenecho ">>> DHCP模式下,$nic 未获取到IP。"return 1fiecho ">>> 测试ping: $PING_TARGET"if ping -c 3 "$PING_TARGET" &> /dev/null; thenecho ">>> 网卡 $nic 已可连通 $PING_TARGET。"return 0elseecho ">>> 虽拿到IP,但无法ping通 $PING_TARGET。"return 2fi
}###############################################################################
# 函数:将当前 DHCP 下发的IP/Gateway/DNS 转为静态
###############################################################################
make_static_config() {local nic="$1"echo ">>> 读取 $nic 的IP/Gateway/DNS,准备写入静态配置..."local ip_cidrip_cidr=$(ip -4 addr show dev "$nic" | grep -oP '(?<=inet\s)\S+')local gatewaygateway=$(ip route | grep -E "^default .* $nic" | awk '{print $3}')local dns_listdns_list=$(grep -E '^nameserver' /etc/resolv.conf | awk '{print $2}' | xargs echo)dns_list="$dns_list 8.8.8.8 114.114.114.114"# 拼成 YAML 列表local dns_yaml="["local first=1for dns in $dns_list; doif [[ $first -eq 1 ]]; thendns_yaml="$dns_yaml$dns"first=0elsedns_yaml="$dns_yaml, $dns"fidonedns_yaml="$dns_yaml]"echo ">>> 生成最终静态配置 $CONFIG_FILE"cat <<EOF > "$CONFIG_FILE"
network:version: 2renderer: networkdethernets:$nic:addresses:- $ip_cidr
EOFif [[ -n "$gateway" ]]; thencat <<EOF >> "$CONFIG_FILE"routes:- to: defaultvia: $gateway
EOFficat <<EOF >> "$CONFIG_FILE"nameservers:addresses: $dns_yamldhcp4: no
EOFchmod 600 "$CONFIG_FILE"echo ">>> netplan apply (static) on $nic..."netplan applyecho ">>> 再次测试ping: $PING_TARGET"if ping -c 3 "$PING_TARGET" &> /dev/null; thenecho ">>> $nic (静态) 可成功访问 $PING_TARGET。"elseecho ">>> 警告:$nic (静态) 依然无法ping通 $PING_TARGET。"fi
}###############################################################################
# 主循环:对每个网卡检查
###############################################################################
found_working_nic=falsefor nic in $NICS; doecho "=== 检查网卡: $nic ==="# 如果网卡是 DHCP (dynamic),直接转静态if ip -4 addr show dev "$nic" | grep -q "dynamic"; thenecho ">>> 网卡 $nic 已是 DHCP 模式,直接转换为静态..."make_static_config "$nic"found_working_nic=truebreakelse# 否则尝试强制 DHCPif try_dhcp_and_test "$nic"; thenecho ">>> 成功拿到IP并连通外网,现在转为静态..."make_static_config "$nic"found_working_nic=truebreakelseecho ">>> $nic DHCP 尝试失败或无法连接外网,继续下一个网卡..."rm -f "$CONFIG_FILE"fifi
doneif [ "$found_working_nic" = false ]; thenechoecho "没有任何网卡成功配置DHCP并连通外网,退出,不做最终保存。"
fiecho
echo "===== [脚本结束] ====="

五、总结

该脚本是一个“先判断是否已有可用静态网络,若否再进行DHCP→静态”的综合示例。
主要功能与注意事项包括:

1、如果脚本检测到已有静态网络并可访问外网,则不修改任何配置;
2、备份后清空 /etc/netplan/,避免旧文件干扰;
3、逐一尝试网卡:若已是 DHCP,直接将其当前分配信息转静态;否则强制启用 DHCP,能连通就转静态,不能就尝试下一个网卡;
4、最终只固定找到的首个可用网卡。若无可用网卡,全局退出、不写任何新的 netplan 文件;
5、DNS 默认追加 8.8.8.8 与 114.114.114.114,可按需改成只使用这两个;
6、警惕 SSH 断开、无 netplan try 回滚等风险,确保有可回退或带外访问方式。

在实际生产环境,通常只需在安装或首配时运行此脚本一次,一旦拿到稳定 IP 并静态化,后续就可无需重复执行。

原创 K8sCat DevOpsAI

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866189.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Snmpwalk工具如何在Windows和Linux的使用方法

一、什么是SNMP协议 SNMP(简单网络管理协议),顾名思义是一种网络管理的协议。SNMP是网络设备一个日常网络运维同行经常接触到的一个协议,不管是设备硬件系统的监控还是软件发出的告警,通通都能通过SNMP协议进行监控。SNMP总共有三个版本可以选择,通常选择的版本为v2c,因为…

万字长文,让你一文轻松掌握卡尔曼滤波!

万字长文,让你一文轻松掌握卡尔曼滤波!!!最近由于有个项目需要使用到目标追踪,于是便想着来复习一下卡尔曼滤波器,但是我发现目前网路上对卡尔曼滤波的教学大致呈现出了两家分化的趋势,即要么通篇都是理论,要么就是直接给一长串代码让你看,因此我打算参考这篇博客深入…

【流量分析】通过流量查看主机关键信息

主机信息包括:Host信息;操作系统信息;账户信息(域环境);一、如何找到Host信息? 一般通过DHCP或者NBNS两种协议,找到Host信息。NBNS是网络基本输入/输出系统(NetBIOS)名称服务器协议,是TCP/IP上的NetBIOS(NetBT)协议族的一部分,它在基于NetBIOS名称访问的网络上提…

进阶markdown语法

系统复习markdown进阶语法 目录系统复习markdown进阶语法1.文字颜色,字体,大小,文字高亮1.1 文字颜色1.2 文字字体1.3 文字高亮1.4 文字字号2.转义字符3. 表格3.1 基础表格3.2 带有对齐方式表格3.3 复杂表格4.脚注4.1 语法4.2 运用场景5.上下标5.1 上标5.2下标6. Tolist7. 锚…

基础markdown语法

系统复习markdown基础语法 1.分级标题 # 一级标题 ## 二级标题 ### 三级标题 #### 四级标题 ##### 五级标题 ###### 六级标题2.段落 直接回车即为分段 这是第一段 这是第二段这是换行这是第一段 这是第二段 这是换行 3.换行符 如果你需要换>=2行,那么只用回车是不可以的,我…

.NET 响应式编程 System.Reactive 系列文章(三):Subscribe 和 IDisposable 的深入理解

在 Rx 中,Subscribe() 方法返回一个 IDisposable 接口对象,用于手动取消订阅和释放资源。另外,System.Reactive 还提供了不返回 IDisposable 的 Subscribe 重载,这些重载方法通过 CancellationToken 管理订阅的生命周期。在本篇文章中,我们将深入探讨 Subscribe 和 IDispo…

【关节电机专栏】ESP32-S3控制大然电机

如何进行CAN初始化? 以下是ESP32-TWAI-CAN库的CAN总线初始化函数(begin()) bool begin(TwaiSpeed twaiSpeed = TWAI_SPEED_500KBPS, int8_t txPin = -1, int8_t rxPin = -1,uint16_t txQueue = 0xFFFF, uint16_t rxQueue = 0xFFFF,twai_filter_config_t* fConfig = nullptr,…

1.2.7 PMU设计中常见问题的分析解答

PMU设计中常见问题的分析解答 在 PMU(电源管理单元)设计中,常见的问题通常涉及电源性能、热管理、效率、安全性等多个方面。以下是一些常见问题及其分析与解答: 1. 输出电压不稳定 问题:PMU 的输出电压无法达到预期,存在较大的波动。 原因分析:负载变化:当负载发生变化…

1.2.6 PMU电源的散热处理及主要事项

PMU电源的散热处理及主要事项 PMU(Power Management Unit,电源管理单元)作为电子设备中实现电源调节和转换的重要组件,其散热处理至关重要,因为过高的温度会影响性能、可靠性和寿命。以下是 PMU 电源的散热处理方法及主要事项。 一、PMU 电源的散热处理方法选择合适的封装…

1.2 PMU

PMU PMU(Power Management Unit,电源管理单元)是一种集成电路(IC),用于管理和调节电子设备中的电源和电压供应。PMU 的设计旨在提高能源利用效率,减少能量损耗,并确保设备在各种操作条件下的稳定运行。以下是关于 PMU 的详细介绍,包括其功能、组成部分、工作原理和应用…

1. 电源模块

电源模块 电源模块是将电源转换、调节和管理功能集成在一个单元中的电子设备。它们通常用于提供电力和接口,确保电子设备在运行过程中获得稳定的电源供应。以下是关于电源模块的详细讲解,包括其类型、特性、应用等。 1. 什么是电源模块? 电源模块是集成多个组件(如变压器、…

第3章 命名准则

第3章 命名准则 1 大小写约定 1 标识符的大小写规则​DO​: 命名空间 、 类型 、 成员 和 泛型参数 ,使用 PascalCasing 风格命名。‍​DO​​:参数,使用 camelCasing 风格命名。‍标识符 大小写 示例命名空间 Pacal namespace System.Security类型 Pacal public class S…