我发现最有价值的脚本不是 “炫技的复杂代码”,而是 “能解决实际问题的实用工具”—— 比如磁盘满了能自动告警,数据能定时备份不丢,批量创建用户不用重复敲命令,系统资源能生成报告供分析。早年我手动做这些事时,每天要花 2 小时在重复操作上,还总因为疏忽出错;后来写了这四类实用脚本,不仅把时间省下来做更重要的事,系统稳定性也提升了不少。如今梳理 “实用脚本开发”,才明白这些脚本就像运维的 “得力助手”:不用多聪明,但能把 “杂活、累活、重复活” 干好,这才是脚本的真正价值。

运维的自动化
1. 实用脚本开发:解决实际问题的 “工具集”
开发实用脚本的核心不是 “用多高级的语法”,而是 “摸透运维场景的需求”—— 磁盘监测要 “及时告警”,备份脚本要 “安全不丢数据”,用户管理要 “高效不出错”,系统统计要 “清晰易分析”。下面这四类脚本,几乎覆盖了日常运维 80% 的重复工作,学会了就能大幅提升效率。
(1)磁盘监测脚本:系统的 “磁盘保镖”
磁盘满是运维最常见的故障之一 —— 要是业务日志没及时清理,或者某个目录突然堆满大文件,磁盘使用率会快速飙升,一旦到 100%,系统可能卡死、业务无法写入数据。磁盘监测脚本就像 “磁盘保镖”,实时盯着磁盘使用率,超过阈值就发告警,不用人手动查看。
核心逻辑:用df命令获取磁盘使用率,筛选出关键分区(比如/、/data),判断是否超过阈值(比如 90%),超过就用邮件发告警。
完整脚本示例:
#!/bin/bash
# 磁盘监测脚本:使用率超过阈值发告警邮件
# 配置参数
THRESHOLD=90 # 告警阈值(百分比)
TO="ops_team@example.com" # 收件人邮箱
SUBJECT="【警告】服务器磁盘使用率超标 $(date +%Y%m%d %H:%M)"
ALERT_CONTENT="以下分区使用率超过${THRESHOLD}%,请及时处理:\n"
# 1. 用df获取磁盘信息,筛选出需要监测的分区(排除tmpfs等临时分区)
# df -h:人类可读格式;grep -v tmpfs:排除临时分区;awk '{print $5,$6}':提取使用率和分区
disk_info=$(df -h | grep -v tmpfs | awk '{print $5,$6}')
# 2. 循环判断每个分区的使用率
echo "$disk_info" | while read usage mount_point; do
# 去掉使用率的%号,转成数字
usage_num=${usage%\%}
# 判断是否超过阈值
if [ $usage_num -gt $THRESHOLD ]; then
ALERT_CONTENT="${ALERT_CONTENT}- 分区:${mount_point},使用率:${usage}\n"
fi
done
# 3. 若有超标分区,发送告警邮件
if [ "${ALERT_CONTENT}" != "以下分区使用率超过${THRESHOLD}%,请及时处理:\n" ]; then
# 追加磁盘详细信息,方便排查
ALERT_CONTENT="${ALERT_CONTENT}\n磁盘详细信息:\n$(df -h)"
# 用mailx发送邮件
echo -e "$ALERT_CONTENT" | mailx -s "$SUBJECT" "$TO"
echo "[$(date)] 磁盘告警邮件已发送" >> /var/log/disk_monitor.log
else
echo "[$(date)] 所有分区使用率正常" >> /var/log/disk_monitor.log
fi
实战细节:
- 用grep -v tmpfs排除临时分区(比如/dev/shm),这些分区不用监测;
- 提取使用率时要去掉%号(${usage%\%}是 Shell 的字符串截取,去掉末尾的%),不然无法做数字比较;
- 告警邮件里追加df -h的详细信息,运维人员不用登录服务器,就能知道哪个目录占空间多;
- 加日志记录,方便后续追溯 “什么时候发过告警”。
当年我在生产环境部署这个脚本后,有次/data分区因为日志没清理超标,脚本 10 分钟内就发了告警,我登录后用du -sh /data/*快速找到大文件,避免了业务受影响 —— 要是没这个脚本,可能要等业务报错才知道。
(2)备份脚本:数据的 “搬运工”
数据是系统的 “生命线”—— 数据库、配置文件、业务日志丢了,可能导致业务中断、数据无法恢复。备份脚本就像 “数据搬运工”,定期把重要数据归档,存到安全的地方(比如本地备份目录、远程服务器),还能记录备份结果,出问题时能追溯。
核心逻辑:用tar归档需要备份的文件 / 目录,按日期命名备份文件(避免覆盖),结合cron定时执行,备份成功 / 失败都记录日志,失败还能发告警。
完整脚本示例:
#!/bin/bash
# 多目录备份脚本:归档文件+定时执行+日志记录+失败告警
# 配置参数
BACKUP_DIR="/backup" # 本地备份目录
# 需要备份的目录列表(用空格分隔)
SOURCE_DIRS="/etc /var/lib/mysql /home/www"
BACKUP_FILE="backup_$(date +%Y%m%d_%H%M%S).tar.gz" # 按时间命名备份文件
LOG_FILE="/var/log/backup.log"
TO="ops_team@example.com"
SUBJECT="【警告】备份失败 $(date +%Y%m%d %H:%M)"
# 1. 检查备份目录是否存在,不存在则创建
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
echo "[$(date)] 创建备份目录:$BACKUP_DIR" >> "$LOG_FILE"
fi
# 2. 用tar归档备份(-z:压缩成gz格式;-c:创建归档;-f:指定文件名;--exclude:排除不需要备份的目录)
echo "[$(date)] 开始备份:$SOURCE_DIRS" >> "$LOG_FILE"
tar -zcf "$BACKUP_DIR/$BACKUP_FILE" --exclude="/var/lib/mysql/tmp" $SOURCE_DIRS
# 3. 判断备份是否成功
if [ $? -eq 0 ]; then
# 备份成功:记录日志,显示备份文件大小
BACKUP_SIZE=$(du -sh "$BACKUP_DIR/$BACKUP_FILE" | awk '{print $1}')
echo "[$(date)] 备份成功!备份文件:$BACKUP_DIR/$BACKUP_FILE,大小:$BACKUP_SIZE" >> "$LOG_FILE"
# 可选:删除7天前的旧备份,避免磁盘占满
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
echo "[$(date)] 删除7天前的旧备份" >> "$LOG_FILE"
else
# 备份失败:记录日志,发告警邮件
echo "[$(date)] 备份失败!请检查源目录是否存在:$SOURCE_DIRS" >> "$LOG_FILE"
echo -e "备份失败!\n失败时间:$(date)\n需要备份的目录:$SOURCE_DIRS\n请登录服务器查看详细日志:$LOG_FILE" | mailx -s "$SUBJECT" "$TO"
fi
定时配置:
用crontab -e添加定时任务,比如每天凌晨 2 点执行备份:
0 2 * * * /opt/scripts/backup.sh
实战细节:
- 用--exclude排除不需要备份的目录(比如 MySQL 的临时目录/var/lib/mysql/tmp),这些目录备份了没用,还占空间;
- 备份文件按 “年月日_时分秒” 命名($(date +%Y%m%d_%H%M%S)),就算一天备份多次,也不会覆盖;
- 加 “删除旧备份” 的逻辑(find ... -mtime +7 -delete),避免备份目录堆满旧文件,导致磁盘满;
- 备份失败时发告警邮件,运维人员能及时排查(比如源目录被删除、磁盘满导致无法写入备份文件)。
当年我用这个脚本备份数据库,有次服务器断电导致备份中断,脚本发了告警邮件,我第二天一早就重新备份,没影响数据完整性 —— 要是没告警,可能过几天才发现备份丢了。
(3)用户管理脚本:批量操作的 “效率工具”
运维中常需要 “批量创建用户”—— 比如新员工入职,一次要创建 10 个账号;或者搭建测试环境,需要多个测试用户。手动用useradd创建,不仅慢,还容易输错密码;用户管理脚本能批量处理,还能输出操作结果,方便核对。
核心逻辑:定义需要创建的用户名列表,循环用useradd创建用户,用echo "密码" | passwd --stdin 用户名设置密码(避免交互),最后输出 “成功 / 失败” 的用户列表。
完整脚本示例:
#!/bin/bash
# 批量创建用户脚本:设置初始密码+输出操作结果+记录日志
# 配置参数
USER_LIST=("user01" "user02" "user03" "user04" "user05") # 需要创建的用户列表
INIT_PASS="Ops@123456" # 初始密码(实际环境建议后续强制修改)
LOG_FILE="/var/log/user_manage.log"
SUCCESS_USERS=() # 存储创建成功的用户
FAIL_USERS=() # 存储创建失败的用户
# 1. 循环创建每个用户
for user in "${USER_LIST[@]}"; do
echo "[$(date)] 开始创建用户:$user" >> "$LOG_FILE"
# 先判断用户是否已存在(id命令能查用户,不存在则返回非0)
if id "$user" &>/dev/null; then
echo "[$(date)] 用户$user已存在,跳过" >> "$LOG_FILE"
FAIL_USERS+=("$user(已存在)")
continue
fi
# 创建用户:-m 自动创建家目录;-s 指定默认Shell为bash
useradd -m -s /bin/bash "$user"
if [ $? -ne 0 ]; then
echo "[$(date)] 用户$user创建失败" >> "$LOG_FILE"
FAIL_USERS+=("$user(创建失败)")
continue
fi
# 设置初始密码:--stdin 从标准输入读密码,避免交互
echo "$INIT_PASS" | passwd --stdin "$user"
if [ $? -eq 0 ]; then
echo "[$(date)] 用户$user创建成功,初始密码:$INIT_PASS" >> "$LOG_FILE"
SUCCESS_USERS+=("$user")
# 可选:强制用户首次登录修改密码
passwd -e "$user"
else
echo "[$(date)] 用户$user密码设置失败" >> "$LOG_FILE"
userdel -r "$user" # 删除已创建的用户(避免残留)
FAIL_USERS+=("$user(密码设置失败)")
fi
done
# 2. 输出操作结果
echo -e "\n==== 批量创建用户结果 ===="
echo "创建成功的用户(共${#SUCCESS_USERS[@]}个):"
for user in "${SUCCESS_USERS[@]}"; do
echo "- $user"
done
echo "创建失败的用户(共${#FAIL_USERS[@]}个):"
for user in "${FAIL_USERS[@]}"; do
echo "- $user"
done
echo "详细日志请查看:$LOG_FILE"
实战细节:
- 创建用户前先用id "$user"判断是否已存在,避免重复创建报错;
- 用useradd -m -s /bin/bash创建用户:-m自动创建家目录(/home/用户名),-s /bin/bash指定默认 Shell,不然用户登录后可能没有命令行;
- 设置密码用passwd --stdin,支持从管道读密码,不用手动输入(适合脚本自动化);
- 加passwd -e "$user"强制用户首次登录修改密码,避免初始密码泄露导致安全风险;
- 若密码设置失败,用userdel -r "$user"删除已创建的用户(-r连家目录一起删),避免残留垃圾文件。
当年新员工入职,一次要创建 20 个用户,我用这个脚本 5 分钟就搞定了,还输出了清晰的结果列表,比手动敲 20 次useradd快多了,也没出错。
(4)系统统计脚本:资源的 “体检报告”
运维需要定期了解 “系统状态”——CPU 使用率高不高?内存够不够用?进程有没有异常?系统统计脚本就像 “系统体检报告”,用top/vmstat/ps等命令获取资源信息,整理成清晰的格式,方便分析系统负载、排查性能问题。
核心逻辑:用top获取 CPU 和内存使用情况,用vmstat获取系统 IO 和进程状态,用ps获取占用资源最高的进程,最后把这些信息整理成报告,输出到屏幕或保存到文件。
完整脚本示例:
#!/bin/bash
# 系统资源统计脚本:CPU+内存+IO+进程分析,生成体检报告
# 配置参数
REPORT_FILE="/var/log/system_stats_$(date +%Y%m%d).log"
DATE=$(date +%Y%m%d\ %H:%M:%S)
# 1. 写入报告头部
echo "==================== 系统资源统计报告 ====================" > "$REPORT_FILE"
echo "统计时间:$DATE" >> "$REPORT_FILE"
echo "服务器 hostname:$(hostname)" >> "$REPORT_FILE"
echo "==========================================================" >> "$REPORT_FILE"
# 2. CPU使用情况(top -bn1:非交互模式,只输出一次;grep Cpu:筛选CPU信息)
echo -e "\n【1】CPU使用情况:" >> "$REPORT_FILE"
top -bn1 | grep "Cpu(s)" | awk '{print "总体使用率:" 100-$8 "%" "(空闲:" $8 "%" ")"}' >> "$REPORT_FILE"
# 统计每个CPU核心的使用率(适合多核心服务器)
echo "各核心使用率:" >> "$REPORT_FILE"
top -bn1 | grep -E "^%Cpu" | awk '{print "核心" NR-1 ":" 100-$8 "%" "(空闲:" $8 "%" ")"}' >> "$REPORT_FILE"
# 3. 内存使用情况(free -h:人类可读格式)
echo -e "\n【2】内存使用情况:" >> "$REPORT_FILE"
free -h | awk '/Mem/ {print "总内存:" $2 ", 已用:" $3 ", 可用:" $7 ", 使用率:" $3/$2*100 "%" }' >> "$REPORT_FILE"
# 4. 磁盘IO情况(vmstat 1 2:采样1次,间隔1秒,取第二次结果避免初始值)
echo -e "\n【3】磁盘IO情况(vmstat):" >> "$REPORT_FILE"
vmstat 1 2 | tail -n1 | awk '{print "每秒读块数:" $9 ", 每秒写块数:" $10 ", 等待IO的进程数:" $17}' >> "$REPORT_FILE"
# 5. 占用资源最高的进程(前10个)
echo -e "\n【4】占用CPU最高的前10个进程:" >> "$REPORT_FILE"
ps -eo pid,ppid,pcpu,pmem,cmd --sort=-pcpu | head -n11 | awk 'NR==1{print "PID 父PID CPU% 内存% 命令"} NR>1{printf "%-5d %-5d %-5.1f %-5.1f %s\n", $1,$2,$3,$4,$5}' >> "$REPORT_FILE"
echo -e "\n【5】占用内存最高的前10个进程:" >> "$REPORT_FILE"
ps -eo pid,ppid,pcpu,pmem,cmd --sort=-pmem | head -n11 | awk 'NR==1{print "PID 父PID CPU% 内存% 命令"} NR>1{printf "%-5d %-5d %-5.1f %-5.1f %s\n", $1,$2,$3,$4,$5}' >> "$REPORT_FILE"
# 6. 报告结束
echo</doubaocanvas>
四类实用Shell脚本提升运维效率


被折叠的 条评论
为什么被折叠?



