Shell脚本如何实现心跳检测

wen 实用脚本 15

Shell脚本实现心跳检测:从原理到实战的完整指南

目录导读

  1. 什么是心跳检测?为什么需要Shell脚本实现?
  2. 心跳检测的核心原理与常见场景
  3. Shell脚本实现心跳检测的三种主流方案
  4. 实战案例:监控Web服务与数据库服务
  5. 高级技巧:日志记录、告警与自动恢复
  6. 常见问题与优化建议(含问答)
  7. 总结与最佳实践

什么是心跳检测?为什么需要Shell脚本实现?

心跳检测(Heartbeat Detection) 是指通过定期发送探测信号,确认目标服务、主机或进程是否存活的技术,它在运维监控、高可用架构、分布式系统中至关重要。

Shell脚本如何实现心跳检测

使用Shell脚本实现心跳检测的核心优势在于:

  • 无需安装额外工具,Linux系统原生支持
  • 轻量级,资源消耗极低
  • 灵活性强,可快速定制检测逻辑
  • 便于集成到Cron或Systemd定时任务中

问答1:Shell脚本心跳检测适合哪些场景?
答:适合中小规模服务器监控、无监控代理的容器环境、临时故障排查、自建高可用集群中的健康检查(如Keepalived结合Shell脚本)。


心跳检测的核心原理与常见场景

1 检测原理

心跳检测通常包含三个步骤:

  1. 发送探测:通过网络请求、进程检查或文件状态判断目标是否在线
  2. 接收响应:等待并解析返回的状态码、超时时间或进程PID
  3. 触发动作:根据结果记录日志、发送告警或执行恢复脚本

2 常见检测场景

场景 检测方式 典型命令
Web服务 HTTP状态码 curl -o /dev/null -s -w "%{http_code}"
TCP端口 连接测试 nc -zv 192.168.1.1 80
进程存活 PID检查 pgrep nginxps -ef | grep [n]ginx
网络连通 ICMP ping ping -c 1 -W 2 8.8.8.8
磁盘/内存 系统指标 df -hfree -m

问答2:为什么推荐用nc而不是ping检测端口?
答:ping依赖ICMP协议,部分云服务商或防火墙会屏蔽ICMP,而nc直接检测TCP端口更加准确,且能区分服务是否真正运行。


Shell脚本实现心跳检测的三种主流方案

基于curl的HTTP服务检测

#!/bin/bash
# 文件名:http_heartbeat.sh
URL="https://example.com/health"
EXPECTED_CODE=200
LOG_FILE="/var/log/heartbeat.log"
response=$(curl -o /dev/null -s -w "%{http_code}" --connect-timeout 5 --max-time 10 "$URL" 2>/dev/null)
if [ "$response" -eq "$EXPECTED_CODE" ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') [SUCCESS] HTTP $response" >> $LOG_FILE
else
    echo "$(date '+%Y-%m-%d %H:%M:%S') [FAIL] HTTP $response" >> $LOG_FILE
    # 触发告警(如发送邮件或钉钉通知)
    /usr/local/bin/send_alert.sh "服务异常,状态码: $response"
fi

基于nc的TCP端口检测

#!/bin/bash
# 文件名:tcp_heartbeat.sh
HOST=$1
PORT=$2
TIMEOUT=3
if nc -zv -w $TIMEOUT $HOST $PORT 2>/dev/null; then
    echo "[OK] $HOST:$PORT 可达"
else
    echo "[FAIL] $HOST:$PORT 不可达"
fi

基于进程与系统资源的综合检测

#!/bin/bash
# 文件名:process_heartbeat.sh
PROCESS_NAME="mysqld"
THRESHOLD_CPU=80
THRESHOLD_MEM=90
# 检测进程是否存在
if ! pgrep -x "$PROCESS_NAME" > /dev/null 2>&1; then
    echo "进程 $PROCESS_NAME 未运行,尝试重启..."
    systemctl restart $PROCESS_NAME
    exit 1
fi
# 检测资源占用
CPU_USAGE=$(ps aux | grep -w "$PROCESS_NAME" | awk '{sum+=$3} END {print sum}')
MEM_USAGE=$(ps aux | grep -w "$PROCESS_NAME" | awk '{sum+=$4} END {print sum}')
if (( $(echo "$CPU_USAGE > $THRESHOLD_CPU" | bc -l) )); then
    echo "[WARN] CPU过高: $CPU_USAGE%"
fi

问答3:curl检测时超时时间如何设置更合理?
答:建议--connect-timeout设为3-5秒,--max-time设为10-15秒,过长超时会导致脚本阻塞,过短则可能误判正常响应慢的服务。


实战案例:监控Web服务与数据库服务

1 综合脚本示例

#!/bin/bash
# 文件名:all_in_one_heartbeat.sh
# 功能:同时检测Nginx和MySQL服务
SERVICES=(
    "nginx,80,http,192.168.1.10"
    "mysql,3306,tcp,192.168.1.11"
)
LOG="/var/log/heartbeat_$(date +%Y%m%d).log"
ALERT_SCRIPT="/opt/alert/send_sms.sh"
for service in "${SERVICES[@]}"; do
    IFS=',' read -r name port type host <<< "$service"
    if [ "$type" == "http" ]; then
        status=$(curl -o /dev/null -s -w "%{http_code}" http://$host:$port/health 2>/dev/null)
        if [ "$status" != "200" ]; then
            echo "$(date) [WARN] $name 异常,状态码: $status" >> $LOG
            $ALERT_SCRIPT "$name 服务异常"
        fi
    elif [ "$type" == "tcp" ]; then
        if ! nc -zv -w 5 $host $port 2>/dev/null; then
            echo "$(date) [FAIL] $name 端口不可达" >> $LOG
            $ALERT_SCRIPT "$name 端口异常"
        fi
    fi
done

2 定时执行(Cron配置)

# 每2分钟执行一次心跳检测
*/2 * * * * /opt/scripts/all_in_one_heartbeat.sh

问答4:多个服务检测时如何避免脚本执行过慢?
答:建议使用&后台并行执行检测任务,或调整超时时间,对于大型集群,可考虑将检测逻辑拆分为独立进程。


高级技巧:日志记录、告警与自动恢复

1 带时间戳的日志格式

LOG_FILE="/var/log/heartbeat_$(date +%Y%m%d).log"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$(hostname)] [检测结果] 详细内容" >> $LOG_FILE

2 多通道告警集成

# 钉钉机器人告警
function send_dingtalk() {
    curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=TOKEN" \
        -H "Content-Type: application/json" \
        -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$1\"}}"
}
# 邮件告警
function send_email() {
    echo "$1" | mail -s "心跳检测告警" admin@yourdomain.com
}

3 自动恢复脚本片段

# 检测到Nginx挂掉后自动重启
if ! nc -zv localhost 80 2>/dev/null; then
    echo "尝试重启Nginx..."
    systemctl restart nginx
    sleep 5
    # 再次验证
    if nc -zv localhost 80 2>/dev/null; then
        echo "重启成功"
    else
        send_alert "Nginx重启失败,需要人工介入"
    fi
fi

问答5:自动重启服务是否安全?
答:建议设置重启次数上限(如3次/小时),并配合状态文件防止无限重启,生产环境应优先告警,避免自动操作导致服务雪崩。


常见问题与优化建议(含问答)

Q:心跳检测间隔设置多长时间合适?
A:Web服务建议30秒-2分钟;数据库建议1-5分钟,间隔越短资源消耗越大,需平衡实时性与负载。

Q:如何避免误报(False Positive)?
A:采用三次重试机制:连续失败3次才触发告警;或结合多节点交叉验证(如A节点检测B节点,B节点检测C节点)。

Q:并发检测时如何防止资源竞争?
A:使用进程锁(如flock)确保同一时间只运行一个检测实例:

exec 200>/var/lock/heartbeat.lock
flock -n 200 || exit 1

Q:检测结果如何可视化?
A:将日志输出到Prometheus格式(需安装prometheus-node-exporter)或使用ELK收集日志。


总结与最佳实践

核心要点

  1. 选择正确的检测方式:HTTP/TCP/进程检测各有适用场景,避免过度使用ping
  2. 设置合理的超时与重试:防止误报和脚本阻塞
  3. 记录结构化日志:方便后续分析,日志建议包含时间、主机、服务、状态码
  4. 告警分级:区分WARN(需要关注)与CRITICAL(需立即处理)

最佳实践清单

  • 脚本应设置set -e或异常处理逻辑
  • 生产环境避免直接使用rm -rf等危险命令
  • 测试阶段使用--dry-run模式先行验证
  • 定期轮转日志并使用logrotate管理

问答6:有没有现成的开源心跳检测工具可以替代Shell脚本?
答:有,如Prometheus(复杂场景)、Monit(中间件)、Uptime Kuma(Web界面),但Shell脚本在轻量部署、临时排查和定制需求方面仍不可替代。

通过本文的多方案对比与实战代码,您可以根据实际场景快速构建可靠的心跳检测体系,从最简单的端口检查到多服务自动恢复,Shell脚本都能胜任,关键在于合理设计重试、告警与恢复的逻辑闭环。

抱歉,评论功能暂时关闭!