ss -tulnp | grep :端口号仅显示监听状态和进程,无法反映实际客户端连接数;需用ss -tn4 state established | grep :端口号或lsof -itcp -stcp:established -p -n -p pid统计真实活跃连接。

ss -tulnp | grep :端口号 能看到监听状态,但看不到连接数
这个命令只告诉你端口有没有被监听、由哪个进程在监听,比如 ss -tulnp | grep :8090 输出中出现 LISTEN,说明 WebSocket 服务进程(如 swoole 或 nginx)确实在跑,但它不反映当前有多少客户端连上来了。
常见错误现象:服务明明在线,curl -i http://localhost:8090 能通,但 ss -tulnp 查不到 ESTABLISHED 连接——大概率是 WebSocket 握手后升级为长连接,而 ss 默认不实时刷新或过滤了非 LISTEN 状态;也可能是连接刚建立就断开,没被捕捉到。
-
ss -tn state established | grep :8090才能查真实活跃连接(需 root 权限) - 加
-o可看连接存活时间:ss -tno state established | grep :8090 - IPv6 混入时干扰判断,强制只看 IPv4:
ss -tn4 state established | grep :8090
lsof -iTCP -sTCP:ESTABLISHED -P -n -p PID 统计连接最准
WebSocket 连接本质是 TCP 连接,所以得从进程维度查它的 TCP 文件描述符数量。比起模糊的全局统计,锁定具体服务进程 PID 后再查,结果更可靠,尤其适合 Swoole/Workerman 这类常驻进程。
使用场景:你已经用 ss -tulnp | grep :8090 拿到 PID(比如 12345),现在想确认它到底维持了多少个 WebSocket 客户端连接。
- 先确认 PID 对应进程是否还在:
ps -p 12345 -o pid,comm,user,cmd - 再统计它的 ESTABLISHED 连接数:
lsof -iTCP -sTCP:ESTABLISHED -P -n -p 12345 | wc -l - 如果输出为 0,但你知道有用户连着,检查是否用了 Unix socket 或反向代理(如 nginx 把 WebSocket 请求转给了后端,此时连接实际在 nginx 进程里)
netstat -an | grep :端口号 | grep ESTABLISHED 不推荐但有时管用
在旧系统或容器里没有 ss 和 lsof 时,netstat 是唯一选择。但它容易漏项,尤其高并发下解析慢、超时返回空,或者非 root 用户执行时看不到 PID 列。
性能影响明显:每执行一次 netstat -an 都要遍历整个 /proc/net/ 目录树,而 ss 直接调内核接口,快一个数量级。
- 最低可用命令:
netstat -an | grep :8090 | grep ESTABLISHED | wc -l - 加
-t限定 TCP:netstat -ant | grep :8090 | grep ESTABLISHED - 别信
netstat -tulnp | grep :8090的 PID 字段——它可能显示错进程,因为权限不足导致解析失败,字段被截断或填充默认值
连接数突然归零或持续增长,优先查进程是否 fork 出子进程
像 Swoole 这类框架默认启用多 worker 模式,主进程(master)监听端口,真正处理连接的是多个子进程(worker)。你用 ss 或 lsof 查到的 PID 往往是 master,它本身不持有连接,所以统计为 0;而每个 worker 的 PID 是动态生成的,且不直接绑定端口。
容易踩的坑:kill 掉 master 进程后,worker 还在跑,连接数不降;或者只 kill 了一个 worker,其他 worker 仍在收包,看起来“杀不死”。
- 查所有相关进程:
ps aux | grep -E "(swoole|workerman|php.*cli)" - 看进程树关系:
ps --forest -o pid,ppid,comm,args | grep -A5 -B5 8090 - 彻底清理:
pkill -f "php.*websocket"或kill -9 $(pgrep -f "swoole-server")(注意匹配精度,避免误杀)











