第4章 Shell脚本与自动化:变量、循环、正则、调试技巧与编写场景

Shell脚本是Linux运维交付工程师的“肌肉记忆”,面试中高频考察变量作用域、循环控制、正则匹配、调试手段及实战脚本设计。本章围绕三大核心问答,帮你构建从语法到工程化的完整回答框架。

Shell 回答框架 1. 理解需求 明确输入/输出/边界 2. 核心语法 变量/循环/正则 3. 异常处理 set -e / trap / 退出码 4. 测试验证 dry-run / 边界用例 5. 优化总结 性能 / 可维护性 提问时按此路径组织回答,体现工程思维

核心知识表:Shell脚本调试技巧对比

调试方式 命令/语法 适用场景 注意事项
逐语句跟踪 set -x 或 bash -x script.sh 定位变量赋值、分支判断 输出冗长,生产慎用
错误即停止 set -e 防止错误无声继续 管道中需用 set -o pipefail
退出陷阱 trap 'cmd' EXIT/ERR 清理临时文件、记录日志 避免在陷阱中再次触发陷阱
手动日志 echo "DEBUG: ..." 重要变量/步骤监控 上线前清理调试输出

面试问题1:请编写一个Shell脚本,批量检查多个主机的网络连通性

考察点:循环遍历、if条件判断、ping命令使用、输出格式化、超时设置。

回答框架:① 定义主机列表(数组或文件);② for循环遍历;③ ping -c 1 -W 2 检测;④ 根据返回值输出“可达/不可达”;⑤ 可选:输出汇总报告。

示例回答:
#!/bin/bash
hosts=("192.168.1.1" "192.168.1.2")
for ip in "${hosts[@]}"; do
  if ping -c 1 -W 2 "$ip" &>/dev/null; then
    echo "$ip: OK"
  else
    echo "$ip: FAIL"
  fi
done

可能追问:如何并行检查多个主机?你如何防止脚本卡死?

避坑提醒:不要在脚本内硬编码密码或敏感信息;生产环境使用超时参数(-W)避免僵尸进程。

面试问题2:如何在Shell脚本中处理字符串替换和正则匹配?举例说明

考察点:sed/awk/grep基础、正则表达式的熟练度、变量替换(Bash内置)。

回答框架:① 明确需求(替换/提取/校验);② 选择工具:简单替换用 ${var//old/new};③ 复杂匹配用 sed -E 或 grep -P;④ 测试正则避免回溯陷阱。

示例回答:
# 变量替换
str="hello world"
echo "${str//world/WORLD}"   # hello WORLD

# 正则提取IP
ip=$(echo "IP: 10.0.0.1" | grep -oP '\d+\.\d+\.\d+\.\d+')

可能追问:贪婪匹配与非贪婪匹配的区别?在sed中如何实现非贪婪?

避坑提醒:注意转义字符:sed中使用 \{ 表示数量,grep -P 需要PCRE支持;生产环境慎用 eval。

面试问题3:你在编写Shell脚本时如何进行调试?请说出至少三种方法

考察点:调试意识、set命令家族、trap使用、生产环境安全调试。

回答框架:① 开发期用 bash -x 或 set -x 查看执行过程;② 关键点位加 echo 输出变量值;③ 用 set -e 捕获未处理错误;④ 用 trap '...' EXIT 保证清理。

示例回答:“我通常先用 bash -x script.sh 跟踪每一步,发现变量异常后改用 set -x 只调试问题区间;再配合 set -e -o pipefail 确保错误不扩散;最后用 trap 'rm -f /tmp/xxx' EXIT 清理临时文件。”

可能追问:生产环境如何安全调试?如果脚本已经上线,如何定位资源泄漏?

避坑提醒:禁止在生产环境直接使用 set -x 输出敏感信息;调试完成后务必删除调试语句;使用 trap 时注意不要覆盖内置信号。

面试加分点:提到 shellcheck 静态分析工具,展示工程化习惯;主动说明使用 getopts 处理命令行参数;提到将常变参数抽取为配置文件,避免硬编码。
高频陷阱提醒:
• 变量未引号包裹导致空格分裂 → 永远使用 "$var"
• 循环内修改全局变量未预期 → 使用 local 声明局部变量
• 正则中使用 [* 未转义 → 用 [\*] 或字符类
• 管道后变量赋值丢失 → 使用 shopt -s lastpipe 或进程替换