【云原生学习】Linux 网络与 Shell 编程核心知识点精讲 + 实战踩坑

2 阅读9分钟

基础信息栏

学习日期:2026-04-23

所属模块:Linux、云运维、网络基础

学习难度:进阶级

核心标签:#Linux 网络 #Shell 编程 #子网划分 #TCP/IP #数组 #阶乘

学习目标:掌握网卡配置、网络扫描、Shell 数组、IP 计算、路由判断、子网划分、包传递流程

前置知识:Linux 基础命令、TCP/IP 基础、Shell 语法


一、核心知识笔记(理论 + 实操)

1. /etc/sysconfig/network-scripts/ifcfg-eth0 配置格式

标准定义:CentOS/RHEL 系列以太网网卡核心配置文件,用于持久化网络参数,重启网络服务生效。

完整字段解析

  • TYPE=Ethernet:网络类型为以太网
  • BOOTPROTO=static/dhcp/none:IP 获取方式(静态 / 动态 / 无)
  • NAME=eth0:网卡逻辑名称
  • DEVICE=eth0:系统识别的设备名
  • ONBOOT=yes:开机自动激活网卡
  • IPADDR=192.168.1.10:静态 IP 地址
  • NETMASK=255.255.255.0:子网掩码
  • GATEWAY=192.168.1.1:默认网关
  • DNS1=223.5.5.5:首选 DNS
  • DNS2=223.6.6.6:备用 DNS
  • PREFIX=24:子网前缀长度(替代 NETMASK)
  • IPV6INIT=no:关闭 IPv6
  • USERCTL=no:禁止普通用户控制网卡

重启网络命令

systemctl restart network
# 或
nmcli c reload

2. 脚本判断网段内在线主机(ping 扫描)

功能说明:自动获取本机网段,批量 ping 检测,输出在线主机列表。

#!/bin/bash
# 获取本机所在网段(适配多网卡)
subnet=$(ip addr show $(ip route | grep default | awk '{print $5}') | grep inet | grep -v inet6 | awk '{print $2}' | cut -d'/' -f1 | cut -d'.' -f1-3)
​
echo "扫描网段:$subnet.1-254"
echo "在线主机如下:"for i in {1..254}; do
  # -c 1 发1个包,-W 1 超时1秒
  ping -c 1 -W 1 $subnet.$i >/dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo -e "\033[32m $subnet.$i 在线 \033[0m"
  fi
done

3. while read line 计算 /etc/passwd 用户 ID 总和

说明:逐行读取 /etc/passwd,提取 UID(第 3 列),过滤系统无效 UID,累加求和。

#!/bin/bash
sum=0
# IFS=: 按冒号分割,只读取第3列
while IFS=: read -r _ _ uid _ _ _ _; do
  # 判断是否为纯数字 UID
  if [[ $uid =~ ^[0-9]+$ ]]; then
    sum=$((sum + uid))
  fi
done < /etc/passwd
​
echo "当前系统所有用户 UID 总和:$sum"

4. 索引数组、关联数组、字符串处理、高级变量(含示例)

索引数组(下标数字)

# 定义
arr=("apple" "banana" "orange")
# 取值
echo ${arr[0]}    # 第一个元素
echo ${arr[-1]}   # 最后一个元素
echo ${arr[@]}    # 所有元素
echo ${#arr[@]}   # 数组长度
# 遍历
for i in ${arr[@]}; do echo $i; done

关联数组(key-value)

# 必须先声明
declare -A student
student[name]="Tom"
student[age]="22"
student[class]="CS"
# 取值
echo ${student[name]}
echo ${!student[@]}  # 所有key
echo ${student[@]}   # 所有value

字符串处理

str="Linux-Shell-2026"
echo ${#str}          # 长度
echo ${str:0:5}       # 截取 0开始,长度5
echo ${str//-/_}      # 替换所有-为_
echo ${str^^}         # 转大写
echo ${str,,}         # 转小写

高级变量

  • $0:脚本自身文件名
  • 11-9:位置参数
  • $#:参数个数
  • $*:所有参数(整体)
  • $@:所有参数(独立)
  • $?:上一条命令退出码(0 成功,非 0 失败)
  • :当前进程
  • $!:后台最后一个进程 PID

5. 求 10 个随机数的最大值与最小值

#!/bin/bash
nums=()
# 生成10个0~32767随机数
for ((i=0;i<10;i++)); do
  nums[$i]=$RANDOM
doneecho "10个随机数:${nums[@]}"
​
max=${nums[0]}
min=${nums[0]}for n in "${nums[@]}"; do
  (( n > max )) && max=$n
  (( n < min )) && min=$n
doneecho "最大值:$max"
echo "最小值:$min"

6. 递归调用实现阶乘算法

#!/bin/bash
factorial() {
  local n=$1
  # 递归终止条件
  if (( n <= 1 )); then
    echo 1
  else
    # 递归调用自身 n-1
    echo $(( n * $(factorial $((n-1))) ))
  fi
}
​
# 调用示例:求 5 的阶乘
result=$(factorial 5)
echo "5! = $result"

7. 主机到主机的数据包传递过程(精细版)

  1. 应用层:应用程序生成数据,交给传输层。

  2. 传输层:加 TCP/UDP 头(源端口、目标端口、序号、校验和)。

  3. 网络层:加 IP 头(源 IP、目标 IP、协议号、TTL)。

  4. 数据链路层:

    • 查 ARP 表获取目标 MAC
    • 封装 MAC 头(源 MAC、目标 MAC、类型)
  5. 物理层:转为电 / 光信号发送。

  6. 转发过程:

    • 同一网段:交换机根据 MAC 转发
    • 不同网段:路由器查路由表,跨网段转发
  7. 目标主机:

    • 自下而上逐层解包头
    • 按端口交给对应应用程序

8. IP 地址 A、B、C、D 类总结及 IP 组成

IP 地址组成:32 位二进制 → 网络位 + 主机位

  • A 类:1~126

    • 掩码:/8(255.0.0.0)
    • 首位:0
    • 网络数:126,主机数:2^24-2
  • B 类:128~191

    • 掩码:/16(255.255.0.0)
    • 首位:10
    • 网络数:16384,主机数:2^16-2
  • C 类:192~223

    • 掩码:/24(255.255.255.0)
    • 首位:110
    • 网络数:209 万,主机数:2^8-2=254
  • D 类:224~239

    • 组播地址,无掩码、无主机位
  • E 类:240~255,保留

特殊地址

  • 127.0.0.0/8:本地回环
  • 0.0.0.0:默认路由
  • 255.255.255.255:全网广播

9. 201.222.200.111/18 计算

计算步骤

  1. 前缀 /18 → 子网掩码:18 个 1

    • 二进制:11111111.11111111.11000000.00000000
    • 十进制:255.255.192.0
  2. 主机位:32-18=14 位

  3. 可用主机数:2^14 - 2 = 16382

    • 减 2:网络号、广播地址不可用

10. A (10.0.1.1/16) 与 B (10.0.2.2/24) 通信判断

A 的判断逻辑

  1. A 使用自己的子网掩码 /16 计算
  2. A 网络位:10.0.0.0
  3. B 的 IP:10.0.2.2 在 10.0.0.0/16 范围内
  4. A 认为与 B 在同一网段,直接发 ARP 请求

B 的判断逻辑

  1. B 使用自己的掩码 /24
  2. B 网络位:10.0.2.0
  3. A 的 IP:10.0.1.1 不在 B 的网段
  4. B 会把回包发给网关,不直接回复 A

结论

  • A 能发 ARP,但 B 不直接回应
  • 无法正常双向通信

11. 将 10.0.0.0/8 划分 32 个子网

计算步骤

  1. 子网数 32 → 2^5=32,需要借 5 位主机位
  2. 原掩码:/8
  3. 新掩码:8+5=13 → /13
  4. 掩码十进制:255.248.0.0
  5. 每个子网主机位:32-13=19 位
  6. 可用主机数:2^19 - 2 = 524,286

第一个子网:10.0.0.0/13

第二个子网:10.8.0.0/13

步长:8.0.0


二、本节学习总结

  1. 网络配置:掌握 ifcfg-eth0 完整字段、重启方式、IP / 网关 / DNS 配置。

  2. Shell 脚本:

    • 批量 ping 扫描在线主机
    • 读取 /etc/passwd 计算 UID 总和
    • 数组、字符串、高级变量熟练使用
    • 随机数极值、递归阶乘实现
  3. 网络原理:

    • 数据包完整传递流程
    • A/B/C/D 类 IP 划分与地址组成
    • 子网掩码、主机数、网段计算
    • 不同掩码主机通信判断逻辑
  4. 子网划分:可根据子网数快速计算新掩码、主机数、网段范围。


三、面试高频考点

1.Shell 编程面试题

  1. 索引数组与关联数组区别?
  2. * 与 @ 区别?
  3. $? 含义?0 和非 0 代表什么?
  4. 如何遍历数组 / 文件?
  5. 递归函数的核心要素?
  6. 如何生成随机数?如何取最大 / 最小?

2.Linux 网络面试题

  1. ifcfg-eth0 常用配置字段?
  2. 同一网段 / 不同网段通信流程?
  3. ARP 作用?工作过程?
  4. A/B/C 类 IP 范围、掩码、主机数?
  5. 如何计算子网掩码、可用主机数?
  6. 两台主机掩码不同,能否通信?
  7. 数据包从主机 A 到主机 B 的完整流程?
  8. 什么是网络位、主机位、广播地址?

3.实战面试题

  1. 写脚本扫描局域网在线主机。
  2. 写脚本计算 /etc/passwd UID 总和。
  3. 给定 IP / 前缀,计算掩码、主机数、网段。
  4. 两台主机掩码不同,判断是否互通并说明原因。

四、面试高频考点・答案

一、Shell 编程面试题

1. 索引数组与关联数组区别

  • 索引数组:下标是数字,默认从 0 开始,无需提前声明。
  • 关联数组:下标是字符串(Key) ,必须用 declare -A 声明,键值对存储。

2. * 与 @ 区别

  • $*:所有参数视为一个整体字符串
  • $@:所有参数视为独立个体,遍历时更常用。
  • 被双引号包裹时差异最明显。

3. $? 含义?0 和非 0 代表什么

  • $?:上一条命令 / 脚本的退出状态码
  • 0:执行成功
  • 非 0:执行失败(1 通用错误,127 命令未找到等)。

4. 如何遍历数组 / 文件

  • 遍历数组:
for i in "${arr[@]}"; do echo $i; done
  • 遍历文件(按行):
while read line; do echo $line; done < file.txt

5. 递归函数的核心要素

  1. 终止条件:必须有出口,否则死循环。
  2. 自身调用:函数内部调用自己。
  3. 参数递减:每次调用向终止条件靠近。

6. 如何生成随机数?如何取最大 / 最小

  • 随机数:$RANDOM(0~32767)。
  • 取最值:先把第一个值赋给 max/min,再循环逐一比较更新。

二、Linux 网络面试题

1. ifcfg-eth0 常用配置字段

TYPE=Ethernet
BOOTPROTO=static/dhcp
NAME/DEVICE=eth0
ONBOOT=yes
IPADDR=
NETMASK/PREFIX=
GATEWAY=
DNS1=
IPV6INIT=no

2. 同一网段 / 不同网段通信流程

  • 同一网段:

    1. 源主机 ARP 请求目标 MAC。
    2. 目标回复 MAC。
    3. 交换机直接二层转发。
  • 不同网段:

    1. 源主机发给网关
    2. 路由器查路由表转发。
    3. 目标网段内再走二层通信。

3. ARP 作用?工作过程

  • 作用:根据 IP → MAC 地址解析。

  • 过程:

    1. 源发广播 ARP 请求:谁是这个 IP?
    2. 目标单播回复:我的 MAC 是 xx。
    3. 双方缓存 ARP 条目。

4. A/B/C 类 IP 范围、掩码、主机数

  • A 类:1~126,/8,主机数 2^24-2。
  • B 类:128~191,/16,主机数 2^16-2。
  • C 类:192~223,/24,主机数 254。
  • D 类:224~239,组播。

5. 如何计算子网掩码、可用主机数

  • 掩码:前缀 /n → 前 n 位为 1,转十进制。
  • 主机位:32 - n。
  • 可用主机:2^ 主机位 - 2(减网络号 + 广播地址)。

6. 两台主机掩码不同,能否通信

  • 不一定。
  • 一方认为同网段、一方认为不同网段 → 单向通、双向不通
  • 必须双方都认为在同一网段,才能正常互通。

7. 数据包从 A 到 B 完整流程

  1. 应用层数据 → 传输层(加端口)→ 网络层(加 IP)→ 链路层(加 MAC)。
  2. 查 ARP 获取 MAC,封装帧发出。
  3. 交换机 / 路由器转发。
  4. 目标主机自下而上解包,交付应用。

8. 什么是网络位、主机位、广播地址

  • 网络位:标识网段,相同则同网段。
  • 主机位:标识网段内具体主机。
  • 广播地址:主机位全 1,向本网段所有主机发送。

三、实战面试题

1. 写脚本扫描局域网内在线主机(详细思路 + 完整脚本 + 说明)

题目要求

写一个 Shell 脚本,自动检测当前主机所在网段,批量 ping 扫描 1~254,输出在线主机 IP

详细实现思路
  1. 获取本机网卡与 IP:通过默认路由找到出口网卡,避免多网卡干扰。
  2. 提取网段前缀:如 192.168.1,只保留前 3 段。
  3. 循环 ping 扫描:对 1~254 逐个发 1 个包,超时 1 秒,提高速度。
  4. 判断结果:用 $? 判断是否 ping 通。
  5. 输出在线主机:绿色高亮显示,清晰易读。
完整脚本
#!/bin/bash
# 功能:扫描本网段所有在线主机
# 作者:云运维学习笔记

# 1. 获取默认路由使用的网卡
eth=$(ip route | grep default | awk '{print $5}')

# 2. 获取本机IP并提取网段前缀(前3段)
local_ip=$(ip addr show $eth | grep inet | grep -v inet6 | awk '{print $2}' | cut -d'/' -f1)
subnet=$(echo $local_ip | cut -d'.' -f1-3)

echo "===================================================="
echo "当前本机IP:$local_ip"
echo "扫描网段:$subnet.1-254"
echo "===================================================="
echo "在线主机列表:"

# 3. 批量扫描
for i in {1..254};do
  ping -c 1 -W 1 $subnet.$i >/dev/null 2>&1
  if [ $? -eq 0 ];then
    echo -e "\033[32m [在线] $subnet.$i \033[0m"
  fi
done
面试可口述要点
  • ip route 取出口网卡,保证准确性。
  • ping -c 1 -W 1 提高扫描速度。
  • 通过 $? 判断命令是否成功。
  • 输出彩色提示,便于查看。

2. 写脚本计算 /etc/passwd 中所有用户 UID 总和

题目要求

使用 while read line 读取 /etc/passwd,计算所有有效用户 UID 的总和

详细实现思路
  1. /etc/passwd 格式:用户名:密码占位:UID:GID:注释:家目录:Shell
  2. 目标:取第 3 列 UID
  3. 过滤:只保留纯数字 UID,排除异常行。
  4. 累加:初始化 sum=0,逐行相加。
  5. 输出最终结果。
完整脚本
#!/bin/bash
# 功能:计算/etc/passwd所有用户UID总和

sum=0

# 逐行读取,按冒号分割,直接取第3列uid
while IFS=: read -r user x uid gid comment home shell;do

  # 判断uid是否为纯数字(过滤非法/无效行)
  if [[ "$uid" =~ ^[0-9]+$ ]];then
    sum=$((sum + uid))
  fi

done < /etc/passwd

echo "========================================"
echo "系统所有有效用户 UID 总和:$sum"
echo "========================================"
面试可口述要点
  • IFS=: 按冒号分段,直接取列,不用 cut,效率更高。
  • [[ "$uid" =~ ^[0-9]+$ ]] 正则过滤,保证只加数字。
  • 使用 while read 标准读取文件方式。
  • 变量作用域清晰,无脏数据。

3. 给定 IP / 前缀,计算子网掩码、主机数、网段范围

题目示例

201.222.200.111/18 为例,计算:

  1. 子网掩码
  2. 可用主机数
  3. 网段范围
详细计算步骤(面试必按这个说)
  1. 确定前缀位数

    /18 表示前 18 位是网络位

  2. 计算子网掩码

    前 18 位全 1,后 14 位全 0:

    11111111.11111111.11000000.00000000
    

    转十进制:

    255.255.192.0

  3. 计算主机位

    32 - 18 = 14 位

  4. 计算可用主机数

    公式:2^主机位 - 2

    减 2 原因:网络号、广播地址不可分配给主机

    2^14 = 16384
    16384 - 2 = 16382
    

    可用主机数:16382

  5. 网段范围

    块大小(增量):256 - 192 = 64

    第三个字节:200 所在段:192

    网络地址:201.222.192.0/18

    广播地址:201.222.255.255

最终答案
  • 子网掩码:255.255.192.0
  • 可用主机数:16382
  • 网段:201.222.192.0 ~ 201.222.255.255

4. 两台主机掩码不同,判断是否互通并说明原因

题目

A:10.0.1.1/16

B:10.0.2.2/24

问:A 如何判断是否同一网段?A 和 B 能否通信?为什么?

详细回答
① A 的判断逻辑(A 用自己的掩码 /16 判断)
  • A 的掩码:255.255.0.0

  • A 对 B 做 按位与运算:

    10.0.2.2 & 255.255.0.0 = 10.0.0.0
    
  • A 自己的网络位:

    10.0.1.1 & 255.255.0.0 = 10.0.0.0
    
  • 结论:A 认为 B 和自己在同一网段。

② B 的判断逻辑(B 用自己的掩码 /24 判断)
  • B 的掩码:255.255.255.0

  • B 对 A 做按位与:

    10.0.1.1 & 255.255.255.0 = 10.0.1.0
    
  • B 自己的网络位:

    10.0.2.2 & 255.255.255.0 = 10.0.2.0
    
  • 结论:B 认为 A 不在同一网段。

③ 通信结果
  • A 发:直接发 ARP 广播请求 B 的 MAC。
  • B 收:收到后,回包不直接发给 A,而是交给网关。
  • 最终:双向无法正常通信。
最终答案

A 使用自己 /16 掩码计算,认为 B 在同一网段;B 使用 /24 掩码,认为 A 不在同一网段。双方判断不一致,因此无法正常双向通信。


5. 把 10.0.0.0/8 划分 32 个子网

题目

10.0.0.0/8 划分成 32 个子网,求:

  1. 新子网掩码
  2. 每个子网主机数
  3. 前两个子网范围
详细步骤
  1. 求需要借多少位

    子网数 32 → 2^5 = 32

    需要 借 5 位主机位 做子网位。

  2. 计算新掩码

    原掩码:/8

    新掩码:8 + 5 = /13

    二进制:

    11111111.11111000.00000000.00000000
    

    十进制:255.248.0.0

  3. 计算每个子网主机数

    主机位 = 32 - 13 = 19 位

    可用主机 = 2^19 - 2 = 524286

  4. 计算块大小(网段步长)

    第二个字节:256 - 248 = 8

    每段间隔:8.0.0

  5. 前两个子网

    子网 1:10.0.0.0/13

    子网 2:10.8.0.0/13

最终答案
  • 掩码:255.248.0.0(/13)
  • 主机数:524286
  • 步长:8.0.0

6.整体总结Shell 实战:重点考察文件读取、循环、条件判断、命令返回值、数组与字符串。

  1. 网络计算:核心是按位与、网络位、主机位、掩码、主机数
  2. 互通判断:必须双方都认为同网段才能通;一方认为不同则不通。
  3. 子网划分:公式固定:借位=log2(子网数),新掩码 = 原掩码 + 借位。