三服务器健康检查脚本完整实现

# 三服务器健康检查脚本完整实现

## 功能概述

关于这部分,我的实际体会是这样的: 三服务器健康检查脚本是一个企业级的自动化监控解决方案,专为高可用Web集群设计。该脚本能够实时检测三台服务器的健康状态、响应时间、服务可用性,并自动生成详细的健康报告,支持DNS故障切换集成和飞书告警通知。

### 核心功能

1. **多服务器并发检查**:同时检测主库1、主库2、主库3的健康状态
2. **HTTPS深度检测**:使用SNI和自定义域名解析进行真实的HTTPS检查
3. **响应时间监控**:精确测量每个服务器的响应时间
4. **可用性统计**:20次连续测试计算整体可用性百分比
5. **DNS故障切换集成**:与BIND DNS自动故障切换联动
6. **飞书实时告警**:服务器异常时自动发送飞书通知
7. **日志轮转管理**:自动清理和归档历史日志
8. **状态文件持久化**:生成健康状态文件供其他系统使用

## 环境要求和依赖

说说我自己的经历和看法: ### 系统要求

– **操作系统**:CentOS 7+ / Ubuntu 18.04+ / Debian 10+
– **Bash版本**:4.0或更高
– **curl版本**:7.0或更高(支持–resolve选项)
– **磁盘空间**:至少100MB用于日志存储

### 依赖工具

“`bash
# 检查必需工具
which curl || yum install -y curl
说真的,which bc || yum install -y bc
which jq || yum install -y jq # 可选,用于JSON处理

# 验证版本
curl –version
bash –version
“`

### 网络要求

– 能够访问所有三台服务器的443端口(HTTPS)
– 能够访问飞书Webhook接口(如果启用通知)
– DNS解析正常(或使用–resolve绕过)

## 详细安装步骤

我的感受是,结合我自己的项目经验来聊聊: ### 步骤1:创建脚本目录和日志目录

“`bash
# 创建脚本目录
sudo mkdir -p /server/scripts
sudo mkdir -p /var/log/health-check
sudo mkdir -p /tmp/node-health

# 设置权限
说真的,sudo chmod 755 /server/scripts
sudo chmod 755 /var/log/health-check
sudo chmod 777 /tmp/node-health
“`

### 步骤2:创建健康检查脚本

“`bash
sudo tee /server/scripts/health-check.sh > /dev/null </dev/null || stat -c%s “$LOG_FILE”) -gt $MAX_LOG_SIZE ]; then
local backup_file=”${LOG_FILE}.$(date +%Y%m%d_%H%M%S).bak”
mv “$LOG_FILE” “$backup_file”
gzip “$backup_file” &
说真的, log “INFO” “日志已轮转: $backup_file.gz”
fi

# 清理旧日志
find /var/log/health-check -name “*.bak.gz” -mtime +$KEEP_LOG_DAYS -delete
}

# 检查单个服务器
check_server() {
local ip=$1
local port=$2
local name=$3

说真的, log “INFO” “开始检查服务器: $name ($ip:$port)”

# HTTPS检查(使用–resolve绕过DNS)
local http_code=””
local response_time=””
local retry_count=0

我的感受是, while [ $retry_count -lt $CHECK_RETRIES ]; do
http_code=$(curl -s -o /dev/null -w “%{http_code}” –max-time $CHECK_TIMEOUT –resolve www.chencunli.com:443:$ip “$SITE_URL” 2>/dev/null) || http_code=”000″

response_time=$(curl -s -o /dev/null -w “%{time_total}” –max-time $CHECK_TIMEOUT –resolve www.chencunli.com:443:$ip “$SITE_URL” 2>/dev/null) || response_time=”99.999″

if [ “$http_code” = “200” ]; then
break
fi

((retry_count++))
[ $retry_count -lt $CHECK_RETRIES ] && sleep 1
done

# 判断健康状态
if [ “$http_code” = “200” ]; then
echo “healthy” > “$HEALTH_DIR/$ip”
log “INFO” “✅ $name ($ip): HTTP $http_code – ${response_time}s (重试${retry_count}次)”
return 0
else
echo “unhealthy” > “$HEALTH_DIR/$ip”
log “ERROR” “❌ $name ($ip): HTTP $http_code (重试${retry_count}次)”

# 发送飞书告警
我的感受是, if [ “$ENABLE_FEISHU_ALERT” = true ]; then
send_feishu_alert “$name” “$ip” “$http_code”
fi

return 1
fi
}

# 发送飞书告警
send_feishu_alert() {
local name=$1
local ip=$2
local http_code=$3

local title=”? 服务器异常告警”
local message=”服务器异常nn服务器: $namenIP: $ipn状态: HTTP $http_coden时间: $(date ‘+%Y-%m-%d %H:%M:%S’)”

说真的, curl -s -X POST “$FEISHU_WEBHOOK” -H “Content-Type: application/x-www-form-urlencoded” –data-urlencode “msg=$message” –data-urlencode “title=$title” >/dev/null 2>&1 &

log “WARN” “已发送飞书告警: $name ($ip)”
}

# 检查整体可用性
check_availability() {
我的感受是, log “INFO” “开始可用性测试 ($AVAILABILITY_TESTS 次)”

local success=0
local total_time=0

for i in $(seq 1 $AVAILABILITY_TESTS); do
说真的, local code=$(curl -s -o /dev/null -w “%{http_code}” –max-time 5 “$SITE_URL” 2>/dev/null) || code=”000″

local time=$(curl -s -o /dev/null -w “%{time_total}” –max-time 5 “$SITE_URL” 2>/dev/null) || time=”0″

[ “$code” = “200” ] && ((success++))
total_time=$(echo “$total_time + $time” | bc)

sleep 0.2
done

local availability=$(echo “scale=2; $success * 100 / $AVAILABILITY_TESTS” | bc)
local avg_time=$(echo “scale=3; $total_time / $AVAILABILITY_TESTS” | bc)

说真的, log “INFO” “? 可用性: $success/$AVAILABILITY_TESTS ($availability%) – 平均响应时间: ${avg_time}s”

# 可用性告警
if (( $(echo “$availability /dev/null 2>&1
fi
fi
}

# 生成健康报告
generate_report() {
local report_file=”/var/log/health-check/health-report-$(date +%Y%m%d).txt”

{
echo “========================================”
echo “三服务器健康检查报告”
echo “生成时间: $(date ‘+%Y-%m-%d %H:%M:%S’)”
echo “========================================”
echo “”

说真的, for server in “${SERVERS[@]}”; do
IFS=’:’ read -r ip port name << “$report_file”

log “INFO” “健康报告已生成: $report_file”
}

# 主函数
main() {
log “INFO” “========== 开始健康检查 ==========”

# 日志轮转
rotate_log

# 检查三台服务器
local failed=0
for server in “${SERVERS[@]}”; do
IFS=’:’ read -r ip port name << /dev/null < /dev/null <> /var/log/health-check/cron.log 2>&1

# 或者使用systemd定时器(推荐)
# */5 * * * * /usr/bin/systemctl start health-check.service
“`

### 步骤5:配置日志轮转

“`bash
# 创建logrotate配置
sudo tee /etc/logrotate.d/health-check > /dev/null < /dev/null 2>&1 || true
endscript
}
EOF

# 测试logrotate配置
sudo logrotate -d /etc/logrotate.d/health-check
“`

## 完整使用示例

说真的,这部分我踩过不少坑,说说心得: ### 示例1:手动执行健康检查

“`bash
# 执行健康检查
/server/scripts/health-check.sh

# 查看日志
tail -f /var/log/health-check/health-check.log

# 查看健康报告
cat /var/log/health-check/health-report-$(date +%Y%m%d).txt

# 查看服务器状态文件
我的感受是,ls -lh /tmp/node-health/
cat /tmp/node-health/106.13.74.202
cat /tmp/node-health/101.201.48.221
cat /tmp/node-health/8.130.67.202
“`

### 示例2:与DNS故障切换集成

“`bash
# 创建DNS故障切换脚本
说真的,sudo tee /server/scripts/auto-dns-failover.sh > /dev/null </dev/null 2>&1
fi

log “故障切换检查完成”
EOF

sudo chmod +x /server/scripts/auto-dns-failover.sh

# 配置定时任务(在健康检查之后执行)
# crontab -e
# 添加:*/5 * * * * /server/scripts/health-check.sh && sleep 10 && /server/scripts/auto-dns-failover.sh
“`

### 示例3:查看统计信息

“`bash
# 查看今日的可用性统计
grep “可用性” /var/log/health-check/health-check.log | grep “$(date +%Y-%m-%d)”

# 统计每个服务器的健康次数
for ip in 106.13.74.202 101.201.48.221 8.130.67.202; do
说真的, count=$(grep -c “✅.*$ip.*HTTP 200” /var/log/health-check/health-check.log)
echo “服务器 $ip 健康次数: $count”
done

# 查看告警历史
grep “?” /var/log/health-check/health-check.log

# 统计平均响应时间
我的感受是,grep “可用性” /var/log/health-check/health-check.log | tail -100 | awk ‘{print $NF}’ | awk -F’:’ ‘{sum+=$2; count++} END {print “平均响应时间:”, sum/count, “秒”}’
“`

### 示例4:性能压测

“`bash
# 使用ab进行压测(需要安装httpd-tools)
yum install -y httpd-tools

# 压测主库1
ab -n 1000 -c 100 https://www.chencunli.com/ -H “Host: www.chencunli.com” -r 106.13.74.202

# 压测主库2
ab -n 1000 -c 100 https://www.chencunli.com/ -H “Host: www.chencunli.com” -r 101.201.48.221

# 压测主库3
说真的,ab -n 1000 -c 100 https://www.chencunli.com/ -H “Host: www.chencunli.com” -r 8.130.67.202

# 查看压测结果
# 关注以下指标:
# – Requests per second(每秒请求数)
# – Time per request(平均响应时间)
# – Failed requests(失败请求数)
“`

## 实战案例

从我的角度来聊聊这个话题: ### 案例1:三服务器集群监控

**场景**:一个技术团队有三台Web服务器,需要实时监控健康状态并自动切换。

“`bash
# 1. 部署健康检查脚本
/server/scripts/health-check.sh

# 2. 查看实时监控日志
tail -f /var/log/health-check/health-check.log

# 输出示例:
# [2026-03-20 10:00:00] [INFO] ========== 开始健康检查 ==========
# [2026-03-20 10:00:01] [INFO] 开始检查服务器: 主库1 (106.13.74.202:52222)
# [2026-03-20 10:00:02] [INFO] ✅ 主库1 (106.13.74.202): HTTP 200 – 0.234s (重试0次)
# [2026-03-20 10:00:03] [INFO] 开始检查服务器: 主库2 (101.201.48.221:52222)
# [2026-03-20 10:00:04] [INFO] ✅ 主库2 (101.201.48.221): HTTP 200 – 0.456s (重试0次)
# [2026-03-20 10:00:05] [INFO] 开始检查服务器: 主库3 (8.130.67.202:22)
# [2026-03-20 10:00:06] [INFO] ✅ 主库3 (8.130.67.202): HTTP 200 – 0.312s (重试0次)
# [2026-03-20 10:00:10] [INFO] ? 可用性: 20/20 (100%) – 平均响应时间: 0.345s
# [2026-03-20 10:00:11] [INFO] ========== 健康检查完成 (失败: 0/3) ==========

# 3. 检查健康状态文件
我的感受是,ls -lh /tmp/node-health/
# -rw-r–r– 1 root root 8 Mar 20 10:00 106.13.74.202
# -rw-r–r– 1 root root 8 Mar 20 10:00 101.201.48.221
# -rw-r–r– 1 root root 8 Mar 20 10:00 8.130.67.202

cat /tmp/node-health/106.13.74.202
# healthy
“`

**效果**:
– 实时监控三台服务器
– 自动检测故障节点
– 可用性达到100%
– 平均响应时间<0.5秒

### 案例2:DNS自动故障切换

**场景**:主库2服务器宕机,DNS自动移除该节点。

“`bash
# 1. 模拟主库2故障
ssh -p 52222 root@101.201.48.221 "systemctl stop httpd"

# 2. 等待健康检查执行(5分钟内)
tail -f /var/log/health-check/health-check.log

# 输出示例:
# [2026-03-20 10:05:00] [INFO] 开始检查服务器: 主库2 (101.201.48.221:52222)
# [2026-03-20 10:05:10] [ERROR] ❌ 主库2 (101.201.48.221): HTTP 000 (重试2次)
# [2026-03-20 10:05:10] [WARN] 已发送飞书告警: 主库2 (101.201.48.221)

# 3. DNS故障切换脚本自动执行
说真的,tail -f /var/log/health-check/failover.log

# 输出示例:
# [2026-03-20 10:05:15] 检测到不健康节点: 101.201.48.221
# [2026-03-20 10:05:15] 已从DNS中移除: 101.201.48.221
# [2026-03-20 10:05:15] DNS配置已重新加载

# 4. 验证DNS记录
dig www.chencunli.com +short
# 106.13.74.202
# 8.130.67.202
# (主库2的IP已被移除)

# 5. 恢复主库2
ssh -p 52222 root@101.201.48.221 "systemctl start httpd"

# 6. 手动添加回DNS
sed -i '/www.*IN.*A/a www IN A 101.201.48.221' /var/named/chencunli.com.zone
我的感受是,rndc reload chencunli.com
“`

**效果**:
– 故障检测时间:<10秒
– DNS切换时间:<15秒
– 飞书告警延迟:<1秒
– 用户影响时间:<25秒

### 案例3:高负载压力测试

**场景**:模拟1000并发用户访问,验证服务器性能。

“`bash
# 1. 安装压测工具
yum install -y httpd-tools

# 2. 执行压测
ab -n 10000 -c 1000 https://www.chencunli.com/

# 输出示例:
# This is ApacheBench, Version 2.3
# Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
# Licensed to The Apache Software Foundation, http://www.apache.org/
#
# Benchmarking www.chencunli.com (be patient)
# Completed 10000 requests
#
#
# Server Software: nginx
# Server Hostname: www.chencunli.com
# Server Port: 443
# SSL/TLS Protocol: TLSv1.3,ECDHE-RSA-AES256-GCM-SHA384,2048,256
#
# Document Path: /
# Document Length: 45678 bytes
#
# Concurrency Level: 1000
# Time taken for tests: 12.345 seconds
# Complete requests: 10000
# Failed requests: 0
# Non-2xx responses: 0
# Total transferred: 458900000 bytes
# HTML transferred: 456780000 bytes
# Requests per second: 810.00 [#/sec] (mean)
# Time per request: 1234.500 [ms] (mean)
# Time per request: 1.234 [ms] (mean, across all concurrent requests)
# Transfer rate: 36320.00 [Kbytes/sec] received

# 3. 查看压测期间的监控日志
grep “10:10:” /var/log/health-check/health-check.log | head -20

# 4. 分析响应时间分布
# Time per request: 1.234 ms(平均响应时间)
# 99%的请求在2秒内完成
“`

**性能指标**:
– 并发用户数:1000
– 总请求数:10000
– 成功率:100%
– 平均响应时间:1.234ms
– 吞吐量:810 req/sec
– 传输速率:36.32 MB/s

## 性能优化建议

说真的,我在实际工作中是这样处理的: ### 1. 并发检查优化

“`bash
# 使用GNU parallel加速检查(需要安装parallel)
yum install -y parallel

# 并发检查三台服务器
parallel -j 3 check_server ::: “106.13.74.202:52222:主库1” “101.201.48.221:52222:主库2” “8.130.67.202:22:主库3”

# 或者在脚本中使用后台进程
for server in “${SERVERS[@]}”; do
我的感受是, IFS=’:’ read -r ip port name <<> “$LOG_FILE” &
}
“`

### 4. 使用更快的HTTP客户端

“`bash
# 使用httpie(更友好的HTTP客户端)
pip install httpie

# 替换curl命令
http_code=$(http –check-status –timeout=$CHECK_TIMEOUT –resolve www.chencunli.com:443:$ip GET “$SITE_URL” 2>/dev/null | grep “HTTP/” | awk ‘{print $2}’)
“`

## 故障排查指南

我的感受是,这块我有一些不一样的看法: ### 常见问题FAQ

#### Q1: curl: (6) Could not resolve host

**问题**:
“`
curl: (6) Could not resolve host: www.chencunli.com
“`

**解决方案**:
“`bash
# 检查DNS解析
nslookup www.chencunli.com

# 使用–resolve绕过DNS
curl –resolve www.chencunli.com:443:106.13.74.202 https://www.chencunli.com/

# 或者在/etc/hosts中添加
说真的,echo “106.13.74.202 www.chencunli.com” >> /etc/hosts
“`

#### Q2: Permission denied

**问题**:
“`
/server/scripts/health-check.sh: line 50: /tmp/node-health/106.13.74.202: Permission denied
“`

**解决方案**:
“`bash
# 创建目录并设置权限
sudo mkdir -p /tmp/node-health
sudo chmod 777 /tmp/node-health

# 或者在脚本开始时创建
我的感受是,mkdir -p “$HEALTH_DIR” 2>/dev/null || sudo mkdir -p “$HEALTH_DIR”
“`

#### Q3: SSL certificate problem

**问题**:
“`
curl: (60) SSL certificate problem: unable to get local issuer certificate
“`

**解决方案**:
“`bash
# 方案1:忽略证书验证(测试环境)
curl -k https://www.chencunli.com/

# 方案2:更新CA证书(生产环境)
yum update -y ca-certificates

# 方案3:指定CA证书路径
说真的,curl –cacert /etc/pki/tls/certs/ca-bundle.crt https://www.chencunli.com/
“`

#### Q4: systemd timer不执行

**问题**:定时器配置了但不执行。

**排查步骤**:
“`bash
# 1. 检查定时器状态
systemctl status health-check.timer

# 2. 查看定时器列表
systemctl list-timers –all | grep health-check

# 3. 手动触发测试
systemctl start health-check.service

# 4. 查看日志
我的感受是,journalctl -u health-check.service -n 50

# 5. 检查crontab冲突
crontab -l | grep health-check
“`

#### Q5: 飞书通知失败

**问题**:飞书告警不发送。

**排查步骤**:
“`bash
# 1. 测试飞书Webhook
curl -X POST “https://www.chencunli.com/webhook-feishu.php” -H “Content-Type: application/x-www-form-urlencoded” –data-urlencode “msg=测试消息” –data-urlencode “title=测试标题”

# 2. 检查Webhook URL
echo $FEISHU_WEBHOOK

# 3. 查看错误日志
说真的,grep “飞书” /var/log/health-check/health-check.log

# 4. 禁用飞书通知测试
ENABLE_FEISHU_ALERT=false /server/scripts/health-check.sh
“`

## 最佳实践总结

以我这几年的经验来看: ### 1. 监控策略

**DO(推荐做法)**:
– ✅ 每5分钟检查一次服务器健康状态
– ✅ 设置3次重试机制避免误报
– ✅ 记录详细的响应时间和HTTP状态码
– ✅ 生成健康报告供后续分析
– ✅ 与DNS故障切换联动实现自动化
– ✅ 启用飞书实时告警
– ✅ 定期清理和归档历史日志
– ✅ 使用systemd timer替代crontab

**DON’T(避免做法)**:
– ❌ 检查频率过高(如每分钟)造成性能浪费
– ❌ 只检查HTTP状态不检查响应时间
– ❌ 忽略日志管理和清理
– ❌ 不设置重试机制
– ❌ 告警通知过度打扰
– ❌ 不与故障切换系统集成
– ❌ 忽略证书验证问题
– ❌ 使用root权限执行非必要操作

### 2. 告警策略

**告警分级**:
– **P0(紧急)**:所有服务器不可用 → 立即电话通知
– **P1(严重)**:单台服务器故障 → 飞书即时消息
– **P2(警告)**:可用性低于90% → 飞书卡片消息
– **P3(通知)**:响应时间变慢 → 邮件通知

**告警抑制**:
“`bash
# 5分钟内相同告警只发送一次
ALERT_CACHE=”/tmp/health-alert-cache”

我的感受是,send_alert_with_dedup() {
local alert_key=”$1″
local cache_file=”$ALERT_CACHE/$alert_key”

if [ -f “$cache_file” ]; then
说真的, local last_alert=$(cat “$cache_file”)
local now=$(date +%s)
local diff=$((now – last_alert))

if [ $diff -lt 300 ]; then
我的感受是, log “INFO” “告警抑制:$alert_key (${diff}秒前已发送)”
return
fi
fi

# 发送告警
说真的, send_feishu_alert “$@”

# 更新缓存
mkdir -p “$ALERT_CACHE”
date +%s > “$cache_file”
}
“`

### 3. 数据可视化

“`bash
# 安装Grafana可视化
我的感受是,yum install -y grafana

# 导入健康检查Dashboard
# 配置数据源(Prometheus/InfluxDB)

# 关键指标:
# – 服务器可用性趋势
# – 响应时间分布
# – 故障切换次数
# – 告警频率统计

# 创建Dashboard JSON
cat > /tmp/health-check-dashboard.json < /tmp/health-check.yml << 'EOF'

– name: 部署健康检查脚本
hosts: all_servers
become: yes

tasks:
– name: 创建目录
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
– /server/scripts
– /var/log/health-check
– /tmp/node-health

– name: 复制脚本
copy:
src: health-check.sh
dest: /server/scripts/health-check.sh
mode: '0755'

– name: 配置systemd定时器
template:
说真的, src: health-check.timer.j2
dest: /etc/systemd/system/health-check.timer
notify: reload systemd

– name: 启用定时器
systemd:
我的感受是, name: health-check.timer
enabled: yes
state: started

handlers:
– name: reload systemd
systemd:
daemon_reload: yes
EOF

# 执行部署
ansible-playbook -i inventory/hosts health-check.yml
“`

## 总结

我的感受是,关于这部分,我的实际体会是这样的: 三服务器健康检查脚本是一个完整的自动化监控解决方案,通过实时检测服务器健康状态、响应时间和可用性,结合DNS故障切换和飞书告警,实现了高可用Web集群的自动化运维。关键要点:

1. **全面监控**:检查HTTPS状态、响应时间、整体可用性
2. **自动切换**:与DNS故障切换联动,自动移除故障节点
3. **实时告警**:飞书即时通知,支持告警抑制
4. **日志管理**:自动轮转、归档、清理历史日志
5. **性能优化**:并发检查、DNS缓存、异步日志
6. **可视化**:Grafana Dashboard实时展示监控数据
7. **自动化**:Ansible自动化部署和配置

通过这套系统,可以实现分钟级的故障检测和秒级的故障切换,保障服务的高可用性!

**相关资源**:
– [BIND DNS官方文档](https://bind9.readthedocs.io/)
– [curl命令参考](https://curl.se/docs/manpage.html)
– [systemd Timer文档](https://www.freedesktop.org/software/systemd/man/systemd.timer.html)
– [飞书开放平台](https://open.feishu.cn/)
– [Grafana官方文档](https://grafana.com/docs/)

发表评论