Shell脚本实现心跳检测:从原理到实战的完整指南
目录导读
- 什么是心跳检测?为什么需要Shell脚本实现?
- 心跳检测的核心原理与常见场景
- Shell脚本实现心跳检测的三种主流方案
- 实战案例:监控Web服务与数据库服务
- 高级技巧:日志记录、告警与自动恢复
- 常见问题与优化建议(含问答)
- 总结与最佳实践
什么是心跳检测?为什么需要Shell脚本实现?
心跳检测(Heartbeat Detection) 是指通过定期发送探测信号,确认目标服务、主机或进程是否存活的技术,它在运维监控、高可用架构、分布式系统中至关重要。

使用Shell脚本实现心跳检测的核心优势在于:
- 无需安装额外工具,Linux系统原生支持
- 轻量级,资源消耗极低
- 灵活性强,可快速定制检测逻辑
- 便于集成到Cron或Systemd定时任务中
问答1:Shell脚本心跳检测适合哪些场景?
答:适合中小规模服务器监控、无监控代理的容器环境、临时故障排查、自建高可用集群中的健康检查(如Keepalived结合Shell脚本)。
心跳检测的核心原理与常见场景
1 检测原理
心跳检测通常包含三个步骤:
- 发送探测:通过网络请求、进程检查或文件状态判断目标是否在线
- 接收响应:等待并解析返回的状态码、超时时间或进程PID
- 触发动作:根据结果记录日志、发送告警或执行恢复脚本
2 常见检测场景
| 场景 | 检测方式 | 典型命令 |
|---|---|---|
| Web服务 | HTTP状态码 | curl -o /dev/null -s -w "%{http_code}" |
| TCP端口 | 连接测试 | nc -zv 192.168.1.1 80 |
| 进程存活 | PID检查 | pgrep nginx 或 ps -ef | grep [n]ginx |
| 网络连通 | ICMP ping | ping -c 1 -W 2 8.8.8.8 |
| 磁盘/内存 | 系统指标 | df -h、free -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收集日志。
总结与最佳实践
核心要点
- 选择正确的检测方式:HTTP/TCP/进程检测各有适用场景,避免过度使用
ping - 设置合理的超时与重试:防止误报和脚本阻塞
- 记录结构化日志:方便后续分析,日志建议包含时间、主机、服务、状态码
- 告警分级:区分WARN(需要关注)与CRITICAL(需立即处理)
最佳实践清单
- 脚本应设置
set -e或异常处理逻辑 - 生产环境避免直接使用
rm -rf等危险命令 - 测试阶段使用
--dry-run模式先行验证 - 定期轮转日志并使用
logrotate管理
问答6:有没有现成的开源心跳检测工具可以替代Shell脚本?
答:有,如Prometheus(复杂场景)、Monit(中间件)、Uptime Kuma(Web界面),但Shell脚本在轻量部署、临时排查和定制需求方面仍不可替代。
通过本文的多方案对比与实战代码,您可以根据实际场景快速构建可靠的心跳检测体系,从最简单的端口检查到多服务自动恢复,Shell脚本都能胜任,关键在于合理设计重试、告警与恢复的逻辑闭环。