“network is unreachable”在workerman上线后出现,主因是系统网络配置、权限限制或容器/虚拟化环境适配问题,而非workerman自身缺陷;需重点检查绑定ip是否真实存在、systemd是否等待网络就绪、selinux/firewalld是否拦截、docker网络模式及端口映射是否正确。

Workerman 项目上线后报 Network is unreachable,基本不是 Workerman 自身的问题,而是它尝试绑定或连接的网络地址/端口在当前系统环境中不可达。核心原因通常落在系统网络配置、权限限制或容器/虚拟化环境适配上。
检查 Workerman 启动时绑定的 IP 和端口是否合法
Workerman 默认监听 0.0.0.0:2346,但若你手动指定 IP(比如写成 '127.0.0.1' 或某个内网 IP),而该 IP 在服务器上根本不存在或未启用,就会触发这个错误。
- 运行
ip addr show确认你要绑定的 IP 确实出现在某张网卡上(inet行) - 避免硬编码非本机 IP:例如
$worker = new Worker('tcp://192.168.10.5:8080');,除非该 IP 是服务器真实配置的地址 - 生产环境推荐用
0.0.0.0或省略 IP(即'tcp://:8080'),由系统自动选择可用接口 - 如果用 Docker,注意容器内
127.0.0.1指向的是容器自身,不是宿主机;外部访问需映射端口并确保宿主机防火墙放行
确认 systemd 或守护进程启动时缺失网络就绪等待
Workerman 常被 systemd 管理,但若服务定义里没声明依赖网络就启动,start 阶段网卡可能还没 up,导致 bind 失败并报 Network is unreachable。
- 检查
/etc/systemd/system/workerman.service是否包含:After=network.target network-online.targetWants=network-online.target - 不要只写
After=network.target—— 它只表示“网络服务已启动”,不保证网卡已获取 IP;network-online.target才真正等待 DHCP 完成或静态配置就绪 - 改完后执行:
sudo systemctl daemon-reload && sudo systemctl restart workerman - 验证是否生效:
systemctl show workerman.service -p After
排查 SELinux 或 firewalld 干预 socket 绑定
CentOS/RHEL 系统默认开启 SELinux,它可能阻止 PHP 进程监听非标准端口(如非 80/443),表现为 bind 失败并抛出 Network is unreachable(实际是权限拒绝伪装成网络错误)。
- 临时关闭 SELinux 测试:
sudo setenforce 0,再启 Workerman;若恢复则说明是 SELinux 问题 - 永久放行端口(推荐):
sudo semanage port -a -t http_port_t -p tcp 2346(替换为你用的端口) - firewalld 不影响 bind,但会影响外部连接;确认开放端口:
sudo firewall-cmd --list-ports,缺则加:sudo firewall-cmd --add-port=2346/tcp --permanent && sudo firewall-cmd --reload
Docker 容器内报错:宿主机网络模式或端口映射缺失
Workerman 运行在 Docker 中时,Network is unreachable 很大概率是因为容器启动时没正确配置网络,或 PHP 尝试连接一个容器内根本不存在的网关/外部地址。
- 检查启动命令是否用了
--network host:该模式下容器共享宿主机网络命名空间,0.0.0.0绑定才有效;否则默认 bridge 模式需显式-p 2346:2346 - 确认容器内能否访问外网:
docker exec -it your-container ping -c 2 8.8.8.8;失败则看docker network inspect bridge和宿主机 iptables 规则 - Workerman 内部若调用
file_get_contents('http://api.example.com')类请求,需确保容器 DNS 可用(检查/etc/resolv.conf) - 避免在容器内监听
127.0.0.1:它只接受容器内部 loopback 请求,外部无法连入
最易被忽略的一点:Workerman 的 Worker::runAll() 是阻塞式启动,错误发生在初始化阶段(如 bind 失败),日志可能只输出一行就退出。务必用 php start.php start -d 后立刻查 tail -f workerman.log 或 journalctl -u workerman -n 50 -f,而不是只看终端回显。











