从原理到实战,一篇精通
目录导读
- 为什么要监控网络连接数
- 核心监控指标解析
- 脚本编写基础:抓取连接数
- Linux环境下的Shell实现
- Windows环境下的PowerShell实现
- Python跨平台脚本实战
- 连接数异常告警与日志记录
- 常见问题与问答
- 总结与进阶建议
为什么要监控网络连接数
网络连接数(TCP/连接数)是服务器健康度的“体温计”,过高的连接数可能意味着:

- DDoS攻击:大量虚假连接导致服务拒绝
- 程序异常:存在未释放的keep-alive连接
- 性能瓶颈:连接池耗尽影响新用户访问
核心价值:通过脚本实时监控连接数,可以在问题发生前发出预警,避免服务中断,据调研,许多企业曾在高峰期因未监控连接数而出现服务雪崩,损失惨重。
核心监控指标解析
| 指标 | 含义 | 告警阈值参考 |
|---|---|---|
| ESTABLISHED | 已建立的连接数 | >系统上限的70% |
| TIME_WAIT | 主动关闭后的等待连接 | >10000需关注 |
| CLOSE_WAIT | 被动关闭异常连接 | 持续增长需排查 |
| SYN_RECV | 半连接数 | >500可能遭遇SYN Flood |
关键概念:TCP连接状态是监控的核心,不同状态反映不同问题,TIME_WAIT过多通常与高并发短连接有关,而CLOSE_WAIT堆积则是程序bug的典型信号。
脚本编写基础:抓取连接数
无论使用哪种语言,核心命令只有一个——在Linux下通过ss或netstat统计特定状态的连接数:
# 统计ESTABLISHED连接数(推荐ss,性能优于netstat) ss -t state established | grep -c "ESTAB"
注意:ss是netstat的现代替代品,在大型系统上性能更优,如果你的服务器没有ss,使用netstat -an也可以,但注意netstat在部分发行版已被弃用。
Linux环境下的Shell实现
以下脚本实现每10秒监控、记录并自动告警:
#!/bin/bash
# monitor_connections.sh
LOG_FILE="/var/log/connection_monitor.log"
ALARM_THRESHOLD=1000
while true; do
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
ESTAB_COUNT=$(ss -t state established 2>/dev/null | wc -l)
TIME_WAIT_COUNT=$(ss -t state time-wait 2>/dev/null | wc -l)
CLOSE_WAIT_COUNT=$(ss -t state close-wait 2>/dev/null | wc -l)
echo "$CURRENT_TIME ESTAB:$ESTAB_COUNT TW:$TIME_WAIT_COUNT CW:$CLOSE_WAIT_COUNT" >> $LOG_FILE
if [ "$ESTAB_COUNT" -gt "$ALARM_THRESHOLD" ]; then
echo "$CURRENT_TIME ALARM: Established连接数 ${ESTAB_COUNT} 超过阈值 ${ALARM_THRESHOLD}" | tee -a $LOG_FILE
# 发邮件或钉钉通知(此处可扩展)
fi
sleep 10
done
部署方式:
chmod +x monitor_connections.sh ./monitor_connections.sh & # 或使用 nohup 后台运行 nohup ./monitor_connections.sh &
Windows环境下的PowerShell实现
Windows系统使用netstat命令,但格式略有不同:
# monitor_connections.ps1
$logPath = "C:\logs\connection_monitor.log"
$alarmThreshold = 1000
while ($true) {
$time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# 统计ESTABLISHED状态(注意Windows下状态名不同)
$estabCount = (netstat -an | Select-String "ESTABLISHED").Count
$timeWaitCount = (netstat -an | Select-String "TIME_WAIT").Count
$closeWaitCount = (netstat -an | Select-String "CLOSE_WAIT").Count
"$time ESTAB:$estabCount TW:$timeWaitCount CW:$closeWaitCount" | Out-File $logPath -Append
if ($estabCount -gt $alarmThreshold) {
"$time ALARM: 超过阈值 $alarmThreshold" | Out-File $logPath -Append
}
Start-Sleep -Seconds 10
}
提示:Windows上的netstat输出速度较慢,如果连接数巨大(如5万以上),建议改用Get-NetTCPConnection(PowerShell 5.1+):
(Get-NetTCPConnection -State Established).Count
Python跨平台脚本实战
Python脚本可以同时支持Linux和Windows,且数据处理更灵活:
# monitor_connections.py
import subprocess
import time
import sys
from datetime import datetime
def get_connection_count(state="ESTAB"):
"""跨平台获取指定状态的连接数"""
try:
if sys.platform.startswith('linux'):
# Linux下使用ss命令
cmd = f"ss -t state {state.lower()}"
output = subprocess.check_output(cmd, shell=True, text=True)
return len([l for l in output.split('\n') if l.strip()])
elif sys.platform == 'win32':
# Windows下使用netstat
output = subprocess.check_output('netstat -an', shell=True, text=True)
return len([l for l in output.split('\n') if state in l])
else:
raise Exception("不支持的平台")
except Exception as e:
print(f"错误: {e}")
return -1
def monitor_loop(interval=10, threshold=1000, log_file="connection.log"):
while True:
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
estab = get_connection_count("ESTAB")
time_wait = get_connection_count("TIME_WAIT")
close_wait = get_connection_count("CLOSE_WAIT")
log_line = f"{now} ESTAB:{estab} TIME_WAIT:{time_wait} CLOSE_WAIT:{close_wait}"
print(log_line)
with open(log_file, 'a') as f:
f.write(log_line + '\n')
if estab > threshold:
alert_msg = f"{now} ALERT: Established {estab} > {threshold}"
print(alert_msg)
# 此处可集成邮件/API通知
time.sleep(interval)
if __name__ == "__main__":
monitor_loop()
运行方式:
pip install --upgrade # 无需额外依赖 python monitor_connections.py
连接数异常告警与日志记录
告警集成(以钉钉机器人为例):
import requests
def send_dingtalk_alert(msg, webhook_url="https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"):
data = {"msgtype": "text", "text": {"content": msg}}
requests.post(webhook_url, json=data)
日志轮转:使用Python的logging.handlers.RotatingFileHandler自动分割日志,避免文件过大。
多维度监控建议:
- 按IP统计:
ss -tn src :80 dst :80 state established | awk '{print $5}' | cut -d: -f1 | sort | uniq -c可找出异常IP - 按端口分析:监控特定端口(如80/443)的连接分布
常见问题与问答
Q:为什么我的ss命令返回0个连接?
A:通常是因为没加-t参数。ss默认显示所有套接字,加上-t只显示TCP,另外请检查是否有root权限(某些发行版需要sudo)。
Q:TIME_WAIT连接过多怎么处理? A:调优内核参数:
# 允许TIME_WAIT复用和快速回收(谨慎使用) echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf sysctl -p
注意:tcp_tw_recycle在Linux 4.12后已移除,因存在NAT问题。
Q:脚本如何做到不占用过多CPU?
A:1) 使用sleep设置合理间隔(10-60秒);2) 避免在循环内频繁调用外部命令,可使用Python的pyshark库抓取实时数据包;3) 对于大型系统,可改为被动监听系统/proc文件系统。
Q:Windows脚本在服务器上无法运行? A:首先确保PowerShell执行策略允许:
Set-ExecutionPolicy RemoteSigned
某些Windows服务器(如Server Core)可能没有netstat命令,需要使用Get-NetTCPConnection替代。
总结与进阶建议
适合场景:
- 个人博客服务器:简单shell脚本即可
- 企业业务系统:推荐Python脚本+日志+邮件/钉钉告警
- 大型云原生架构:使用Prometheus+Grafana采集
node_netstat_Tcp_CurrEstab指标
进阶玩法:
- 历史趋势分析:将监控数据存入时序数据库(如InfluxDB)
- 自动化修复:当检测到CLOSE_WAIT堆积时,自动重启对应服务的Python子进程
- 分布式监控:通过SSH批量收集多台服务器的连接数(使用Paramiko库)
推荐工具对比: | 方法 | 优点 | 缺点 | |------|------|------| | 纯Shell | 轻量,无依赖 | 逻辑复杂时难以维护 | | Python | 跨平台、易扩展 | 需Python环境 | | 企业级监控 | 可视化、支持历史回溯 | 配置复杂 |
最后提醒:无论选择哪种方式,建议先在测试环境运行一周后再上生产,同时确认脚本不会因为资源消耗导致监控自身变成性能瓶颈,保持监控脚本健壮性——当脚本本身出现异常时,应能通过外部检测(如cron保活)自动恢复。
本文由自动化运维工程师根据实战经验整理,旨在帮助运维人员快速搭建可靠的网络连接数监控体系。