—title: Shell 脚本从入门到写出第一个自动化脚本date: 2026-06-26tags: [shell, bash, 自动化脚本]series: CSDN知识付费—# Shell 脚本从入门到写出第一个自动化脚本## 开篇引言在 Linux/Unix 的世界里Shell 脚本是运维工程师和开发者的必备技能。无论是部署服务、批量处理文件、定时任务还是监控系统状态Shell 脚本都能让你的工作效率提升数倍。不要觉得写脚本很神秘其实它就是把你在终端里手动敲的命令按顺序写进一个文件里。今天我们就从零开始一步步写出属于你的第一个实用自动化脚本。适用人群有 Linux 基础操作经验会 ls、cd、vim的开发者或运维新人。## 核心概念### 什么是 Shell 脚本Shell 脚本是用于命令行解释器如 Bash的一系列命令的集合。它会逐行执行你写好的指令。### 为什么是 BashBashBourne Again Shell是绝大多数 Linux 发行版的默认 shell兼容性好、功能强大。本教程所有示例均基于Bash。### 脚本的执行流程bash# 1. 创建文件touch my_script.sh# 2. 写入代码用 vim 或 echo# 3. 添加执行权限chmod x my_script.sh# 4. 执行脚本./my_script.sh关键点第一行#!/bin/bash是shebang告诉系统用什么解释器执行脚本。## 实战操作6个必备示例 2个自动化脚本### 示例 1Hello World 变量bash#!/bin/bash# 第一个脚本变量定义与输出NAMELinux运维实战echo Hello, $NAMEecho 当前时间: $(date)echo 当前用户: $USER# 数字计算a10b20sum$((a b))echo 10 20 $sum输出结果Hello, Linux运维实战当前时间: Mon Mar 17 10:30:22 CST 2025当前用户: root10 20 30注意变量赋值两边不能有空格否则会报错。### 示例 2条件判断与循环bash#!/bin/bash# 判断文件是否存在 遍历目录TARGET_FILE/tmp/test.txt# 条件判断-f 检测是否为文件if [ -f $TARGET_FILE ]; then echo 文件 $TARGET_FILE 存在else echo 文件不存在正在创建... touch $TARGET_FILE echo 创建成功fi# for 循环遍历当前目录下的 .sh 文件echo echo 当前目录下的 Shell 脚本 for file in *.sh; do if [ -f $file ]; then echo - $file ($(wc -l $file) 行) fidone输出结果文件不存在正在创建...创建成功 当前目录下的 Shell 脚本 - my_script.sh (5 行)### 示例 3函数定义与参数传递bash#!/bin/bash# 定义函数计算文件大小人性化显示human_readable_size() { local bytes$1 if [ $bytes -lt 1024 ]; then echo ${bytes}B elif [ $bytes -lt 1048576 ]; then echo $((bytes / 1024))KB else echo $((bytes / 1048576))MB fi}# 调用函数FILE_PATH/var/log/syslogif [ -f $FILE_PATH ]; then SIZE$(stat -c%s $FILE_PATH) echo $FILE_PATH 的大小为: $(human_readable_size $SIZE)fi输出结果/var/log/syslog 的大小为: 128KB### 示例 4读取文件内容并处理bash#!/bin/bash# 逐行读取 /etc/passwd提取用户名和 shellecho 用户名 | 登录Shellecho -----------------while IFS: read -r username _ uid gid _ home shell; do # 只显示 uid 1000 的普通用户 if [ $uid -ge 1000 ] 2/dev/null; then printf %-10s | %s\n $username $shell fidone /etc/passwd输出结果用户名 | 登录Shell-----------------nobody | /usr/sbin/nologintestuser | /bin/bash### 示例 5错误处理与退出码bash#!/bin/bashset -e # 发生任何错误立即退出cleanup() { echo 脚本被中断正在清理... rm -f /tmp/temp_data_*.txt exit 1}trap cleanup SIGINT SIGTERMecho 开始执行安全操作...# 模拟可能失败的操作mkdir -p /backup || { echo 创建备份目录失败; exit 1; }# 使用 和 || 控制流程ping -c 1 8.8.8.8 /dev/null echo 网络可达 || echo 网络不可达echo 操作完成退出码: $? # 使用 $? 获取上一条命令的退出码输出结果正常情况开始执行安全操作...网络可达操作完成退出码: 0### 示例 6日志记录与时间戳bash#!/bin/bashLOG_FILE/var/log/auto_deploy.loglog_info() { echo [$(date %Y-%m-%d %H:%M:%S)] [INFO] $1 | tee -a $LOG_FILE}log_error() { echo [$(date %Y-%m-%d %H:%M:%S)] [ERROR] $1 | tee -a $LOG_FILE 2}log_info 脚本启动# 模拟部署过程sleep 1log_info 下载依赖包完成sleep 0.5log_info 配置文件已更新# 模拟错误if [ ! -d /nonexistent ]; then log_error 目录 /nonexistent 不存在filog_info 脚本完成### 完整自动化脚本 1批量重命名文件bash#!/bin/bash# 功能将当前目录下的所有 .txt 文件重命名为 日期_原文件名.txtTARGET_EXTtxtTODAY$(date %Y%m%d)COUNT0echo 开始批量重命名 .$TARGET_EXT 文件...for file in *.$TARGET_EXT; do if [ -f $file ]; then NEW_NAME${TODAY}_${file} mv $file $NEW_NAME echo ✓ $file - $NEW_NAME ((COUNT)) fidoneif [ $COUNT -eq 0 ]; then echo 未找到 .$TARGET_EXT 文件else echo ✅ 成功重命名 $COUNT 个文件fi执行效果开始批量重命名 .txt 文件... ✓ notes.txt - 20250317_notes.txt ✓ config.txt - 20250317_config.txt✅ 成功重命名 2 个文件### 完整自动化脚本 2系统健康检查bash#!/bin/bash# 功能检查 CPU、内存、磁盘、进程数异常时发送告警THRESHOLD_CPU80 # CPU 使用率阈值%THRESHOLD_MEM90 # 内存使用率阈值%THRESHOLD_DISK85 # 磁盘使用率阈值%ALERT_EMAILadminexample.comALERT_LOG/var/log/system_alert.logget_cpu_usage() { # 取 1 分钟内的平均 CPU 使用率留一个核心做空闲参考 top -bn1 | grep Cpu(s) | awk {print $2 $4} | cut -d. -f1}get_mem_usage() { free | grep Mem | awk {printf %.0f, $3/$2 * 100}}get_disk_usage() { df / | tail -1 | awk {print $5} | tr -d %}# 收集数据CPU$(get_cpu_usage)MEM$(get_mem_usage)DISK$(get_disk_usage)PROC_COUNT$(ps aux --no-headers | wc -l)# 检测异常ALERT_MSG[ $CPU -gt $THRESHOLD_CPU ] ALERT_MSGCPU 使用率过高: ${CPU}% (阈值: ${THRESHOLD_CPU}%)\n[ $MEM -gt $THRESHOLD_MEM ] ALERT_MSG内存使用率过高: ${MEM}% (阈值: ${THRESHOLD_MEM}%)\n[ $DISK -gt $THRESHOLD_DISK ] ALERT_MSG磁盘使用率过高: ${DISK}% (阈值: ${THRESHOLD_DISK}%)\n# 输出报告echo 系统健康报告 $(date) echo CPU 使用率: ${CPU}%echo 内存使用率: ${MEM}%echo 磁盘使用率: ${DISK}%echo 进程数: ${PROC_COUNT}if [ -n $ALERT_MSG ]; then echo -e \n⚠️ 异常告警: echo -e $ALERT_MSG # 写入日志实际环境可发送邮件 echo [$(date)] 告警: $ALERT_MSG $ALERT_LOGelse echo ✅ 系统状态正常fi输出结果 系统健康报告 Mon Mar 17 10:35:00 CST 2025 CPU 使用率: 23%内存使用率: 45%磁盘使用率: 67%进程数: 189✅ 系统状态正常## 常见坑和解决方案### 坑 1if [ $var value ]变量为空时报错错误示例bashvarif [ $var hello ]; then # 展开后变成 if [ hello ]语法错误 echo equalfi✅ 正确做法bash# 方案一变量加双引号if [ $var hello ]; then echo equalfi# 方案二使用 [[ ]] 增强语法支持正则if [[ $var hello ]]; then echo equalfi### 坑 2for file in *.log没有匹配文件时执行一次错误现象bashfor file in *.log; do echo 处理 $filedone# 如果没有 .log 文件会输出 处理 *.log✅ 正确做法bash# 先检查是否有匹配文件shopt -s nullglob # 启用 nullglob 选项没有匹配返回空for file in *.log; do [ -f $file ] || continue # 跳过空值 echo 处理 $filedoneshopt -u nullglob # 恢复默认### 坑 3$(( ... ))做浮点数运算失败错误示例bashecho $((3 / 2)) # 输出 1整数运算✅ 正确做法bash# 方案一使用 bcecho scale2; 3/2 | bc # 输出 1.50# 方案二使用 awkawk BEGIN {printf \%.2f\n\, 3/2} # 输出 1.50## 总结通过本文你应该已经掌握了以下核心技能| 知识点 | 对应示例 | 实用程度 ||--------|----------|----------|| 变量与字符串处理 | 示例1 | ⭐⭐⭐⭐⭐ || 条件判断与循环 | 示例2 | ⭐⭐⭐⭐⭐ || 函数封装 | 示例3 | ⭐⭐⭐⭐ || 文件读写与流处理 | 示例4 | ⭐⭐⭐⭐ || 错误处理与信号捕获 | 示例5 | ⭐⭐⭐⭐ || 日志记录与调试 | 示例6 | ⭐⭐⭐⭐⭐ ||自动化实践| 批量重命名、系统巡检 |⭐必看|**核心要点回顾**1.写好 shebang#!/bin/bash2.变量加引号避免空格和空值问题3.用set -e和trap增强脚本健壮性4.善用tee和记录日志5.写自动化脚本前先手动执行一次确认逻辑正确从现在开始把重复操作写成脚本。比如每天备份数据库、定时清理日志、批量修改配置文件——自动化的价值会在你喝杯咖啡的时间里体现出来。## 推荐阅读1. Linux 三剑客grep、sed、awk 实战指南 —— 文本处理神器的 20 个高频用法2. Crontab 定时任务从小白到高手 —— 让你的脚本在凌晨自动运行3. Shell 脚本调试技巧与性能优化 —— 解决脚本跑起来慢、找 bug 难的问题