1. 运维工程师的Shell脚本实战:批量排查服务器故障
作为运维工程师,最头疼的莫过于半夜被报警电话吵醒,发现几十台服务器同时出现异常。手动一台台登录检查?等排查完天都亮了。今天我要分享的这套Shell脚本方案,正是为了解决这个痛点而生。经过三年生产环境打磨,这套脚本已经帮我们团队将故障平均响应时间从47分钟缩短到8分钟。
先看一个真实案例:上个月某电商大促期间,监控系统突然显示20多台Web服务器CPU飙高。通过批量执行脚本,我们在90秒内就定位到是某个爬虫脚本异常导致的,迅速封禁IP后系统恢复正常。如果没有这套自动化方案,后果不堪设想。
2. 监控体系架构设计
2.1 三层监控模型
一个健壮的监控体系应该像洋葱一样分层:
- 系统层监控:CPU、内存、磁盘、网络等基础指标
- 服务层监控:Nginx/PHP/MySQL等服务的进程、端口、日志
- 业务层监控:订单成功率、支付响应时间等业务指标
bash复制# 示例:获取系统负载的Shell函数
get_load_avg() {
load=$(uptime | awk -F 'load average:' '{print $2}' | cut -d, -f1 | sed 's/ //g')
echo $load
}
2.2 指标采集频率设计
不同指标的监控频率需要差异化设置:
| 指标类型 | 采集频率 | 告警阈值 |
|---|---|---|
| CPU使用率 | 10秒 | >90%持续5分钟 |
| 内存使用 | 30秒 | >85% |
| 磁盘空间 | 5分钟 | /分区>90% |
| 服务进程状态 | 15秒 | 进程不存在 |
3. 核心脚本开发实战
3.1 单机健康检查脚本
先实现一个基础版检查脚本health_check.sh:
bash复制#!/bin/bash
# 定义告警阈值
CPU_WARN=90
MEM_WARN=85
DISK_WARN=90
# CPU检查
check_cpu() {
local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
if (( $(echo "$cpu_usage > $CPU_WARN" | bc -l) )); then
echo "[CRITICAL] CPU使用率 ${cpu_usage}%"
return 1
fi
return 0
}
# 内存检查(适配不同Linux发行版)
check_mem() {
local mem_total mem_free mem_used mem_usage
if free -V | grep -q 'GNU coreutils'; then
mem_total=$(free -m | awk '/Mem:/{print $2}')
mem_used=$(free -m | awk '/Mem:/{print $3}')
else
mem_total=$(free -m | grep 'Mem:' | awk '{print $2}')
mem_used=$(free -m | grep 'Mem:' | awk '{print $3}')
fi
mem_usage=$((mem_used*100/mem_total))
if [ $mem_usage -gt $MEM_WARN ]; then
echo "[CRITICAL] 内存使用率 ${mem_usage}%"
return 1
fi
return 0
}
注意:内存计算在不同Linux发行版上命令输出有差异,需要做兼容处理
3.2 批量执行方案
通过SSH批量执行的核心逻辑:
bash复制# servers.txt格式:ip username port
execute_all() {
local script=$1
while read -r line; do
ip=$(echo $line | awk '{print $1}')
user=$(echo $line | awk '{print $2}')
port=$(echo $line | awk '{print $3}')
echo "==== $ip ===="
ssh -p $port $user@$ip 'bash -s' < $script
echo
done < servers.txt
}
4. 高级功能实现
4.1 自动修复机制
对于已知问题可以直接修复:
bash复制# 自动清理/tmp目录
clean_tmp() {
local usage=$(df /tmp | tail -1 | awk '{print $5}' | tr -d '%')
if [ $usage -gt 90 ]; then
echo "开始自动清理/tmp..."
find /tmp -type f -mtime +7 -delete
echo "清理完成,当前使用率: $(df /tmp | tail -1 | awk '{print $5}')"
fi
}
4.2 监控报告生成
用awk生成HTML报告:
bash复制gen_report() {
echo "<html><body><h2>服务器健康报告</h2><table border=1>"
echo "<tr><th>服务器IP</th><th>CPU</th><th>内存</th><th>磁盘</th></tr>"
awk '
BEGIN {FS=":"; OFS="</td><td>"}
/====/ {ip=substr($2,2,length($2)-2)}
/CRITICAL/ {
if ($0 ~ /CPU/) cpu=$2
else if ($0 ~ /内存/) mem=$2
else if ($0 ~ /磁盘/) disk=$2
}
/^$/ {
print "<tr><td>" ip, cpu?cpu:"正常", mem?mem:"正常", disk?disk:"正常" "</td></tr>"
cpu=mem=disk=""
}
' logfile.txt
echo "</table></body></html>"
}
5. 生产环境避坑指南
-
SSH连接优化:
- 使用
-o ConnectTimeout=10设置超时 - 配置SSH长连接保持(修改/etc/ssh/sshd_config):
code复制ClientAliveInterval 60 ClientAliveCountMax 3
- 使用
-
性能采集准确性问题:
- CPU使用率建议采样3次取平均值:
bash复制cpu_usage=$(top -bn3 | grep "Cpu(s)" | tail -1 | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}') - 内存统计推荐使用
free -m而非/proc/meminfo,兼容性更好
- CPU使用率建议采样3次取平均值:
-
批量执行注意事项:
- 控制并发数量(用xargs或parallel):
bash复制cat servers.txt | xargs -P 5 -I {} sh -c 'ssh {} "hostname"' - 敏感操作建议先加
--dry-run参数试运行
- 控制并发数量(用xargs或parallel):
这套脚本体系在我们生产环境已经稳定运行3年,日均执行超过2万次检查。建议先从基础监控开始,逐步添加业务指标。记住:好的监控系统不是一蹴而就的,需要持续迭代优化。