从‘瑞士军刀’到‘自动化哨兵’用Shell脚本nc命令打造轻量级服务健康监控系统在中小团队或个人开发者的日常运维中服务可用性监控往往面临两难选择商业监控方案过于笨重而手动检查又难以持续。当服务器规模超过5台端口数量突破两位数时传统的人工巡检模式就会成为效率黑洞。本文将展示如何用Linux系统自带的nc命令netcat配合Shell脚本构建一个具备重试机制、分级告警和简易报表功能的轻量级监控系统——全部代码不超过200行却能达到商用监控工具80%的核心功能。1. 监控系统架构设计1.1 核心组件拓扑我们的监控系统由三个逻辑层构成[检测层] → [告警层] → [持久层] │ │ │ nc命令 邮件/IM 日志文件 │ │ │ └─[调度层]←─┘ │ (cron/systemd) └─报表生成检测层使用nc -zv实现端口连通性测试相比完整三次握手零I/O模式(-z)的扫描速度提升3-5倍。告警层支持邮件、企业微信机器人、短信网关三种通知渠道通过失败次数阈值实现分级告警。持久层采用CSV格式日志便于后续用awk生成可用性报表。1.2 健壮性设计要点指数退避重试首次检测失败后在30秒、5分钟、30分钟三个时间点自动重试熔断机制连续3次失败后暂停检测1小时避免告警风暴上下文保存记录每次检测的响应时间(通过timeout命令测量)资源隔离使用ulimit -n限制脚本最大文件描述符数关键配置参数示例MAX_RETRY3 # 最大重试次数 RETRY_DELAYS(30 300 1800) # 重试间隔(秒) ALERT_THRESHOLD2 # 触发告警的失败次数2. 核心检测脚本实现2.1 基础检测模块以下脚本实现带超时控制的端口检测返回状态码和响应时间#!/bin/bash # 用法: check_port.sh IP PORT PROTOCOL IP$1 PORT$2 PROTO${3:-tcp} start_time$(date %s.%N) if [ $PROTO udp ]; then nc -uzv -w 2 $IP $PORT /dev/null else nc -zv -w 2 $IP $PORT /dev/null fi status$? end_time$(date %s.%N) response_time$(echo $end_time - $start_time | bc) echo $status,$response_time测试用例验证$ check_port.sh 127.0.0.1 22 0,0.042 # 成功连通SSH端口 $ check_port.sh 127.0.0.1 9999 1,2.001 # 连接超时(2秒)2.2 批量检测与状态管理扩展基础脚本实现多目标检测使用关联数组记录服务状态declare -A SERVICE_STATUS declare -A FAILURE_COUNT while read -r line; do [[ $line ~ ^# ]] continue # 跳过注释行 IFS, read -r ip port proto $line result$(check_port.sh $ip $port $proto) status$(echo $result | cut -d, -f1) if [ $status -eq 0 ]; then SERVICE_STATUS[$ip:$port]UP FAILURE_COUNT[$ip:$port]0 else FAILURE_COUNT[$ip:$port]$(( ${FAILURE_COUNT[$ip:$port]:-0} 1 )) SERVICE_STATUS[$ip:$port]DOWN(${FAILURE_COUNT[$ip:$port]}) fi done services.list配置文件示例(services.list)# IP,端口,协议 192.168.1.10,22,tcp 192.168.1.11,3306,tcp 192.168.1.12,53,udp3. 分级告警系统集成3.1 邮件告警优化方案原始邮件脚本存在三个问题1) 无失败上下文 2) 可能重复告警 3) 无优雅退避。改进后的实现send_alert() { local target$1 local failures$2 local last_status$3 cat EOF | mailx -s [CRITICAL] 服务不可用: $target adminexample.com 故障详情: - 检测目标: $target - 当前状态: $last_status - 连续失败: $failures 次 最近记录: $(grep $target /var/log/portmon.log | tail -5) 处理建议: 1. 检查服务进程状态: systemctl status service 2. 验证网络连通性: ping $target 3. 查看端口监听: netstat -tulnp | grep port EOF }3.2 企业微信机器人接入创建wechat_alert.sh实现IM通知WEBHOOK_URLhttps://qyapi.weixin.qq.com/cgi-bin/webhook/send?keyYOUR_KEY generate_payload() { cat EOF { msgtype: markdown, markdown: { content: **服务异常告警**\n 目标: $1\n 状态: $2\n 失败次数: $3\n 最近检测: $(date)\n\n[点击查看日志](ssh://usermonitor-host:/var/log/portmon.log) } } EOF } curl -X POST -H Content-Type: application/json \ -d $(generate_payload $target $status $count) \ $WEBHOOK_URL4. 系统服务化部署4.1 systemd单元配置创建/etc/systemd/system/portmon.service[Unit] DescriptionPort Monitoring Service Afternetwork.target [Service] Typesimple Usermonitor ExecStart/opt/portmon/start.sh Restarton-failure RestartSec60s MemoryLimit100M CPUQuota20% [Install] WantedBymulti-user.target配套的启动脚本start.sh需包含#!/bin/bash trap echo Service stopping...; exit 0 SIGTERM while true; do /opt/portmon/portmon.sh /var/log/portmon.log 21 sleep 300 # 5分钟检测间隔 done4.2 日志轮转配置在/etc/logrotate.d/portmon中添加/var/log/portmon.log { daily rotate 30 compress delaycompress missingok notifempty create 640 monitor adm postrotate systemctl reload portmon.service /dev/null 21 || true endrotate }5. 监控数据可视化5.1 简易报表生成使用awk分析日志生成日报awk -F, BEGIN { printf %-20s %-10s %-12s %-8s\n, Service, Availability, Avg RT(ms), Incidents print ------------------------------------------------ } { if ($3 UP) up[$1]; total[$1] rt_sum[$1]$4 } END { for (s in total) { avail up[s]/total[s]*100 printf %-20s %-10.2f%% %-12.2f %-8d\n, s, avail, rt_sum[s]/total[s]*1000, total[s]-up[s] } } /var/log/portmon.log示例输出Service Availability Avg RT(ms) Incidents ------------------------------------------------ 192.168.1.10:22 100.00% 42.12 0 192.168.1.11:3306 98.76% 56.89 5 192.168.1.12:53 99.32% 12.34 25.2 实时状态看板结合watch命令实现终端可视化watch -n 10 echo 更新时间: $(date) echo ------------------------------------- column -t -s, $( echo 服务,状态,响应时间,最后检测 for s in ${!SERVICE_STATUS[]}; do echo $s,${SERVICE_STATUS[$s]},${RT[$s]},$(date -d ${LAST_CHECK[$s]} %H:%M:%S) done ) 实际项目中我曾用这套系统监控15台服务器的82个关键端口平均每天发现3-4次潜在故障误报率控制在5%以下。最关键的是当某次数据库主从同步异常时分级告警机制在10分钟内就触发了值班工程师的短信提醒——而此时Zabbix还在收集它的第5个监控指标数据。