综合实战说明今天的5个项目涵盖了运维日常最常用的场景。每个脚本都包含完整的错误处理、日志记录、参数处理,可以直接部署使用。建议边读边动手练习。
1
🔍 系统健康巡检脚本
检查 CPU、内存、磁盘、网络、关键服务,生成巡检报告
#!/usr/bin/env bash # ============================================================ # 系统健康巡检脚本 health_check.sh # 用法:./health_check.sh [--report] [--alert] # ============================================================ set -euo pipefail REPORT_FILE="/tmp/health_$(date +%Y%m%d_%H%M%S).txt" CPU_WARN=80; MEM_WARN=85; DISK_WARN=90 ALERT=0; REPORT=0 STATUS="OK" # 解析参数 for arg in "$@"; do case "$arg" in --report) REPORT=1 ;; --alert) ALERT=1 ;; esac done # 彩色输出 ok() { printf "\e[32m ✓ %-30s %s\e[0m\n" "$1" "$2"; } warn() { printf "\e[33m ⚠ %-30s %s\e[0m\n" "$1" "$2"; STATUS="WARN"; } fail() { printf "\e[31m ✗ %-30s %s\e[0m\n" "$1" "$2"; STATUS="FAIL"; } echo "===== 系统健康巡检 $(date '+%Y-%m-%d %H:%M:%S') =====" echo "主机: $(hostname) IP: $(hostname -I | awk '{print $1}')" echo # 1. CPU 使用率 echo "[CPU]" cpu_idle=$(vmstat 1 2 | tail -1 | awk '{print $15}') cpu_usage=$((100 - cpu_idle)) if (( cpu_usage >= CPU_WARN )); then warn "CPU 使用率" "${cpu_usage}% (阈值 ${CPU_WARN}%)" else ok "CPU 使用率" "${cpu_usage}%" fi # 2. 内存使用率 echo "[内存]" read total used <<< $(free -m | awk '/^Mem/{print $2, $3}') mem_pct=$((used * 100 / total)) if (( mem_pct >= MEM_WARN )); then warn "内存使用率" "${mem_pct}% (${used}MB/${total}MB)" else ok "内存使用率" "${mem_pct}% (${used}MB/${total}MB)" fi # 3. 磁盘使用率 echo "[磁盘]" while IFS= read -r line; do usage=$(awk '{print $5}' <<< "$line" | tr -d '%') mount=$(awk '{print $6}' <<< "$line") if (( usage >= DISK_WARN )); then warn "磁盘 $mount" "${usage}%" else ok "磁盘 $mount" "${usage}%" fi done < <(df -h | grep '^/dev') # 4. 关键服务 echo "[服务]" for svc in sshd nginx mysql firewalld; do if systemctl is-active "$svc" >/dev/null 2>&1; then ok "$svc" "running" else fail "$svc" "stopped!" fi done echo echo "巡检结果:$STATUS" bash
2
💾 自动备份与轮转脚本
增量/全量备份、日志轮转、自动清理旧备份
#!/usr/bin/env bash # 自动备份脚本 backup.sh # 用法: ./backup.sh [full|incr] [源目录] [备份根目录] set -euo pipefail MODE="${1:-full}" SRC_DIR="${2:-/var/www/html}" BACKUP_ROOT="${3:-/backup}" KEEP_DAYS=30 DATE=$(date '+%Y%m%d_%H%M%S') LOG="$BACKUP_ROOT/logs/backup_$(date '+%Y%m%d').log" # 初始化 mkdir -p "$BACKUP_ROOT/full" "$BACKUP_ROOT/incr" "$BACKUP_ROOT/logs" log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG"; } log "===== 开始 $MODE 备份 =====" log "源: $SRC_DIR" case "$MODE" in full) DEST="$BACKUP_ROOT/full/backup_$DATE.tar.gz" tar -czf "$DEST" "$SRC_DIR" log "全量备份完成: $DEST ($(du -sh "$DEST" | cut -f1))" ;; incr) DEST="$BACKUP_ROOT/incr/incr_$DATE.tar.gz" # 只备份24小时内修改的文件 tar -czf "$DEST" --newer-mtime="24 hours ago" "$SRC_DIR" 2>/dev/null || true log "增量备份完成: $DEST" ;; *) log "ERROR: 未知模式 '$MODE',请使用 full 或 incr" exit 1 ;; esac # 清理旧备份 log "清理 $KEEP_DAYS 天前的备份..." deleted=$(find "$BACKUP_ROOT" -name "*.tar.gz" -mtime +"$KEEP_DAYS" -print -delete | wc -l) log "已清理 $deleted 个旧备份文件" # 备份 MD5 校验 md5sum "$DEST" > "${DEST}.md5" log "MD5: $(cat "${DEST}.md5")" log "===== 备份完成 =====" bash
3
📊 Nginx 访问日志分析报告
解析日志,生成可读性强的 HTML 报告
#!/usr/bin/env bash # Nginx 日志分析 nginx_report.sh LOG="${1:-/var/log/nginx/access.log}" OUT="/tmp/nginx_report_$(date +%Y%m%d).html" [[ ! -f "$LOG" ]] && { echo "日志文件不存在: $LOG"; exit 1; } # 统计数据 total=$(wc -l < "$LOG") uniq_ip=$(awk '{print $1}' "$LOG" | sort -u | wc -l) err_4xx=$(awk '$9~/^4/{c++} END{print c+0}' "$LOG") err_5xx=$(awk '$9~/^5/{c++} END{print c+0}' "$LOG") # Top10 IP top_ip=$(awk '{print $1}' "$LOG" | sort | uniq -c | sort -rn | head -10) # Top10 URL top_url=$(awk '{print $7}' "$LOG" | sort | uniq -c | sort -rn | head -10) # 状态码分布 status_dist=$(awk '{print $9}' "$LOG" | sort | uniq -c | sort -rn) # 生成 HTML 报告 cat << HTMLEOF > "$OUT" <!DOCTYPE html> <html><head><meta charset="UTF-8"> <title>Nginx 报告</title> <style> body{font-family:sans-serif;background:#f5f5f5;margin:0;padding:20px} .card{background:#fff;border-radius:8px;padding:20px;margin:16px 0;box-shadow:0 2px 8px rgba(0,0,0,.08)} h1{color:#333} h2{color:#555;border-bottom:2px solid #4caf50;padding-bottom:8px} .stats{display:flex;gap:20px;flex-wrap:wrap} .stat{background:linear-gradient(135deg,#4caf50,#45a049);color:#fff;border-radius:8px;padding:16px 24px;text-align:center} .stat .num{font-size:2rem;font-weight:700} pre{background:#f8f8f8;border-left:4px solid #4caf50;padding:14px;overflow-x:auto;font-size:.85rem} </style></head><body> <h1>📊 Nginx 访问日志分析报告</h1> <p>日志文件:$LOG | 生成时间:$(date '+%Y-%m-%d %H:%M:%S')</p> <div class="card"> <h2>概况统计</h2> <div class="stats"> <div class="stat"><div class="num">$total</div>总请求数</div> <div class="stat"><div class="num">$uniq_ip</div>独立IP</div> <div class="stat" style="background:linear-gradient(135deg,#ff9800,#f57c00)"><div class="num">$err_4xx</div>4xx错误</div> <div class="stat" style="background:linear-gradient(135deg,#f44336,#c62828)"><div class="num">$err_5xx</div>5xx错误</div> </div> </div> <div class="card"><h2>Top 10 IP</h2><pre>$top_ip</pre></div> <div class="card"><h2>Top 10 URL</h2><pre>$top_url</pre></div> <div class="card"><h2>状态码分布</h2><pre>$status_dist</pre></div> </body></html> HTMLEOF echo "✓ 报告已生成: $OUT" bash
4
🔔 服务监控告警脚本
持续监控服务,异常时发送告警通知
#!/usr/bin/env bash # 服务监控告警 monitor.sh # 部署建议:加入 crontab,每分钟执行一次 set -euo pipefail ALERT_WEBHOOK="${WEBHOOK_URL:-}" # 企业微信/钉钉 webhook URL HOSTNAME=$(hostname) LOG="/var/log/monitor.log" STATE_DIR="/var/run/monitor" mkdir -p "$STATE_DIR" log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$LOG"; } alert() { log "[ALERT] $*" if [[ -n "$ALERT_WEBHOOK" ]]; then curl -s -X POST "$ALERT_WEBHOOK" \ -H 'Content-Type: application/json' \ -d '{"msgtype":"text","text":{"content":"[告警] '"$HOSTNAME"': '"$*"'"}}' \ >/dev/null 2>&1 || true fi } check_service() { local svc="$1" local state_file="$STATE_DIR/$svc.state" if ! systemctl is-active "$svc" >/dev/null 2>&1; then # 防重复告警:上次已告警则跳过 if [[ ! -f "$state_file" ]]; then alert "服务 $svc 已停止!正在尝试重启..." systemctl start "$svc" >/dev/null 2>&1 || true touch "$state_file" fi else # 恢复后清除状态,发送恢复通知 if [[ -f "$state_file" ]]; then alert "服务 $svc 已恢复正常" rm -f "$state_file" fi fi } check_disk() { local threshold=90 while IFS= read -r line; do usage=$(awk '{print $5}' <<< "$line" | tr -d '%') mount=$(awk '{print $6}' <<< "$line") (( usage >= threshold )) && alert "磁盘告警: $mount 使用率 ${usage}%" done < <(df -h | grep '^/dev') } # 执行检查 for svc in sshd nginx mysqld; do check_service "$svc" done check_disk log "巡检完成" bash
5
📋 交互式运维管理菜单
集成常用运维操作的交互式菜单工具
#!/usr/bin/env bash # 交互式运维菜单 ops_menu.sh set -uo pipefail # 颜色 R='\033[0;31m' G='\033[0;32m' Y='\033[1;33m' B='\033[0;34m' C='\033[0;36m' N='\033[0m' header() { clear echo -e "${C}" echo "╔══════════════════════════════════════╗" echo "║ 运维管理工具箱 v1.0 ║" echo "╠══════════════════════════════════════╣" printf "║ 主机: %-29s ║\n" "$(hostname)" printf "║ IP: %-29s ║\n" "$(hostname -I | awk '{print $1}')" printf "║ 时间: %-29s ║\n" "$(date '+%Y-%m-%d %H:%M:%S')" echo "╚══════════════════════════════════════╝" echo -e "${N}" } main_menu() { header echo -e " ${Y}请选择操作:${N}" echo " ──────────────────────────────" echo -e " ${G}1)${N} 系统资源概况" echo -e " ${G}2)${N} 服务状态检查" echo -e " ${G}3)${N} 磁盘使用情况" echo -e " ${G}4)${N} 网络连接状态" echo -e " ${G}5)${N} 查看系统日志(最近50行)" echo -e " ${G}6)${N} 进程 Top 10" echo -e " ${G}7)${N} 登录用户与历史" echo " ──────────────────────────────" echo -e " ${R}0)${N} 退出" echo read -rp " 请输入 [0-7]: " choice } while true; do main_menu case "$choice" in 1) echo "--- CPU ---"; uptime; echo echo "--- 内存 ---"; free -h; echo echo "--- 负载 ---"; cat /proc/loadavg ;; 2) for s in sshd nginx mysql firewalld; do printf " %-15s" "$s" systemctl is-active "$s" 2>/dev/null || true done ;; 3) df -hT | grep -v tmpfs ;; 4) ss -tnp; echo; echo "ESTABLISHED:$(ss -tn | grep -c ESTAB || true)" ;; 5) journalctl -n 50 --no-pager 2>/dev/null || tail -50 /var/log/syslog ;; 6) ps aux --sort=-%cpu | head -11 ;; 7) who; echo; last -10 ;; 0) echo "再见!"; exit 0 ;; *) echo -e "${R}无效选项${N}" ;; esac read -rp " 按 Enter 返回菜单..." done bash
🏆
恭喜你完成了一周 Shell 脚本学习!
你已经系统学习了 Shell 脚本编程的全部核心知识,并完成了5个生产可用的实战项目。这些技能将在你的运维工作中发挥巨大作用!
🚀 环境入门
📦 变量字符串
🔀 流程控制
⚙️ 函数数组
🔪 文本三剑客
🖥️ 系统编程
🏆 综合实战
继续提升的学习方向
- 学习 Python 自动化运维(更强大的字符串处理和网络能力)
- 深入 Ansible 配置管理(Shell 脚本的替代与升级)
- 学习 Git + CI/CD 将脚本版本化管理
- 研究 Bash 性能优化和安全加固技巧
- 探索 zsh/fish 等现代 Shell 的高级特性