云计算百科
云计算领域专业知识百科平台

《100个“反常识”经验22:用shell写一个服务器健康检查脚本》

本期摘要

服务器监控工具很多(Zabbix、Prometheus、云监控),但有时候你只需要一个轻量级的脚本:每天跑一次,把CPU、内存、磁盘、网络、进程等关键指标汇总成报告,发到邮箱或钉钉。本文从零开始,教你写一个完整的服务器健康检查脚本。包含:获取系统负载、内存使用率、磁盘使用率、僵尸进程数、网络连接状态、最近登录记录、系统错误日志。最后将结果格式化为易读的文本,并自动发送告警。读完你就能定制自己专属的健康检查工具。

为什么需要自己写检查脚本?

场景说明
小团队没有专业监控 写个脚本每天跑一次,成本几乎为零
云监控不够细 自定义检查特定进程、特定端口
监控盲区 比如僵尸进程、时钟同步偏差
定时巡检 每周生成一份健康报告存档

一个完整的健康检查脚本

bash

#!/bin/bash
# 服务器健康检查脚本 v1.0
# 用途:收集系统关键指标,输出报告并发送告警

THRESHOLD_CPU=80 # CPU告警阈值(%)
THRESHOLD_MEM=90 # 内存告警阈值(%)
THRESHOLD_DISK=85 # 磁盘告警阈值(%)
THRESHOLD_ZOMBIE=5 # 僵尸进程告警阈值
REPORT_FILE="/tmp/health_check_$(date +%Y%m%d).txt"
ALERT_EMAIL="admin@example.com"

# 格式化输出函数
print_section() {
echo ""
echo "=========================================="
echo "$1"
echo "=========================================="
}

# 开始生成报告
{
echo "服务器健康检查报告"
echo "检查时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "主机名: $(hostname)"
echo "IP地址: $(hostname -I | awk '{print $1}')"

# 1. CPU负载
print_section "1. CPU状态"
LOAD=$(uptime | awk -F'load average:' '{print $2}')
echo "负载: $LOAD"

CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
echo "CPU使用率: ${CPU_USAGE}%"
if (( $(echo "$CPU_USAGE > $THRESHOLD_CPU" | bc -l) )); then
echo "⚠️ 警告: CPU使用率超过阈值 ${THRESHOLD_CPU}%"
fi

# 2. 内存状态
print_section "2. 内存状态"
MEM_TOTAL=$(free -h | awk '/^Mem:/ {print $2}')
MEM_USED=$(free -h | awk '/^Mem:/ {print $3}')
MEM_FREE=$(free -h | awk '/^Mem:/ {print $4}')
MEM_PERCENT=$(free | awk '/^Mem:/ {printf "%.0f", $3/$2 * 100}')
echo "总内存: $MEM_TOTAL"
echo "已用: $MEM_USED"
echo "空闲: $MEM_FREE"
echo "使用率: ${MEM_PERCENT}%"
if [ $MEM_PERCENT -gt $THRESHOLD_MEM ]; then
echo "⚠️ 警告: 内存使用率超过阈值 ${THRESHOLD_MEM}%"
fi

# 3. 磁盘状态
print_section "3. 磁盘状态"
df -h | grep -v tmpfs | grep -v devtmpfs

# 检查每个分区使用率
df -h | grep -v tmpfs | awk 'NR>1 {print $5,$6}' | while read percent mount; do
usage=$(echo $percent | sed 's/%//')
if [ $usage -gt $THRESHOLD_DISK ]; then
echo "⚠️ 警告: 分区 $mount 使用率 $percent 超过阈值 ${THRESHOLD_DISK}%"
fi
done

# 4. 僵尸进程
print_section "4. 进程状态"
ZOMBIE_COUNT=$(ps aux | awk '$8=="Z"' | grep -v grep | wc -l)
echo "僵尸进程数: $ZOMBIE_COUNT"
if [ $ZOMBIE_COUNT -gt $THRESHOLD_ZOMBIE ]; then
echo "⚠️ 警告: 僵尸进程数超过阈值 $THRESHOLD_ZOMBIE"
ps aux | awk '$8=="Z"'
fi

# CPU占用TOP5
echo ""
echo "CPU占用TOP5:"
ps aux –sort=-%cpu | head -6 | tail -5 | awk '{print $3"%", $11}'

# 内存占用TOP5
echo ""
echo "内存占用TOP5:"
ps aux –sort=-%mem | head -6 | tail -5 | awk '{print $4"%", $11}'

# 5. 网络连接
print_section "5. 网络连接"
ESTABLISHED=$(ss -t state established | tail -n +2 | wc -l)
TIME_WAIT=$(ss -t state time-wait | tail -n +2 | wc -l)
echo "已建立连接: $ESTABLISHED"
echo "TIME_WAIT连接: $TIME_WAIT"

# 检查常见服务端口
echo ""
echo "服务端口检查:"
for port in 22 80 443 3306 6379; do
if ss -tln | grep -q ":$port "; then
echo "✅ 端口 $port 已监听"
else
echo "❌ 端口 $port 未监听"
fi
done

# 6. 最近登录记录
print_section "6. 最近登录"
last -10 | head -10

# 7. 系统错误日志(最近5条)
print_section "7. 系统错误日志"
journalctl -p err -n 5 –no-pager 2>/dev/null || tail -5 /var/log/messages 2>/dev/null

# 8. 时间同步检查
print_section "8. 时间同步"
if command -v chronyc &> /dev/null; then
chronyc tracking | grep "System time"
else
echo "chrony未安装,跳过"
fi

echo ""
echo "=========================================="
echo "检查完成,详细报告已保存至: $REPORT_FILE"
echo "=========================================="

} > $REPORT_FILE

# 输出到屏幕
cat $REPORT_FILE

# 发送告警(如有超过阈值)
if grep -q "⚠️" $REPORT_FILE; then
mail -s "⚠️ 服务器健康检查告警 – $(hostname)" $ALERT_EMAIL < $REPORT_FILE
echo "告警邮件已发送"
fi

如何使用

1. 保存脚本

bash

vi /usr/local/bin/health_check.sh

2. 添加执行权限

bash

chmod +x /usr/local/bin/health_check.sh

3. 手动测试

bash

./health_check.sh

4. 添加到crontab定时执行

bash

# 每天早上8点执行一次
0 8 * * * /usr/local/bin/health_check.sh

# 也可以写到日志文件
0 8 * * * /usr/local/bin/health_check.sh >> /var/log/health_check.log 2>&1

扩展功能:发送到钉钉/企业微信

bash

# 钉钉机器人告警函数
send_dingtalk() {
WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=xxx"
curl -s -X POST $WEBHOOK -H "Content-Type: application/json" -d "{
\\"msgtype\\": \\"text\\",
\\"text\\": {\\"content\\": \\"$1\\"}
}"
}

# 如果有告警,发送到钉钉
if grep -q "⚠️" $REPORT_FILE; then
SUMMARY=$(grep "⚠️" $REPORT_FILE | head -5)
send_dingtalk "服务器告警\\n主机: $(hostname)\\n$SUMMARY"
fi

脚本优化建议

优化点说明
配置文件化 把阈值、邮箱等参数放到外部配置文件
日志归档 检查报告按日期归档,保留30天
远程上报 通过API上报到内部监控平台
多服务器 用ansible批量部署,统一收集结果

下期预告

《100个“反常识”经验23:rsync比scp强在哪?——增量同步详解》

赞(0)
未经允许不得转载:网硕互联帮助中心 » 《100个“反常识”经验22:用shell写一个服务器健康检查脚本》
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!