技术演进中的开发沉思-134 shell编程篇:四类实用脚本

四类实用Shell脚本提升运维效率

我发现最有价值的脚本不是 “炫技的复杂代码”,而是 “能解决实际问题的实用工具”—— 比如磁盘满了能自动告警,数据能定时备份不丢,批量创建用户不用重复敲命令,系统资源能生成报告供分析。早年我手动做这些事时,每天要花 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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值