“address already in use”表示目标端口被其他进程占用,需先用lsof或netstat定位pid,再kill清理;若为workerman残留进程,应通过ps+awk或pgrep强制终止所有相关子进程,并验证端口是否真正空闲。

Workerman启动失败时提示“Address already in use”,说明你要监听的端口(比如2346、8282)正被另一个进程占用,系统拒绝重复绑定——这不是代码写错了,而是操作系统在阻止你抢别人正在用的门牌号。
先确认到底谁占了端口
Linux/macOS下运行:lsof -i :8282(把8282换成你报错里的端口号),直接看到占用该端口的进程名和PID;如果提示command not found,说明没装lsof,改用netstat -tulnp | grep :8282(需root权限才显示进程名)。
Windows用户运行:netstat -ano | findstr :8282,记下最后一列的PID,再执行tasklist | findstr <pid></pid>查进程名。
【注意:别只查127.0.0.1:8282,得查0.0.0.0:8282或:::8282(IPv6),否则可能漏掉真凶】
杀掉占用端口的进程
方法一:如果是其他服务(如Nginx、另一个PHP项目)占了,直接停掉它:sudo systemctl stop nginx 或 kill -15 <pid></pid>(优雅终止)。
方法二:如果是Workerman自己残留的子进程没退干净,别只kill主进程——它们可能还在后台跑着:ps aux | grep workerman 看有没有带start.php或你项目路径的php进程,然后执行:kill -9 $(pgrep -f "your_project_path/start.php")。
方法三:图省事可暴力清理当前用户所有php进程:killall -u $(whoami) php 2>/dev/null(仅限开发环境,生产慎用)。
检查并清理Workerman残留进程
第一步:运行ps aux | grep Worker,重点看COMMAND列是否包含WorkerMan或你的start.php路径。
第二步:若发现残留,用ps aux | grep WorkerMan | awk '{print $2}' | xargs kill -9干掉全部相关进程。
第三步:再运行一次netstat -tuln | grep :8282,确认输出为空——这时候端口才算真正空出来。
这一步漏掉的话,哪怕你改了端口,旧进程还在偷偷占着原端口,新服务照样起不来。
验证端口是否真正释放
执行lsof -i :8282或netstat -tuln | grep :8282,没有任何输出即表示端口已空闲。
如果仍有输出,但PID对应进程已不存在(ps -p <pid></pid>返回空),说明是TIME_WAIT状态残留,此时可在Workerman启动脚本中给Worker加选项:$worker->reusePort = true;启用SO_REUSEADDR(仅限Linux,需PHP 7.4+)。
临时绕过问题:换端口启动
打开start.php,找到类似new Worker('websocket://0.0.0.0:2346')的行,把:2346改成一个未被占用的端口,比如:2347或:8081。
注意:小于1024的端口(如80、443)在Linux下需要root权限,否则会报Permission denied;改完后记得同步更新客户端连接地址,否则连不上。











