先把当时的情况摆出来。DNS 服务要从 53 端口同时提供 TCP 和 UDP,运维在 CentOS 7.9 上先起了 UDP 的监听,再起 TCP 时报 Address already in use,ss -lnup 和 ss -lntp 看是两个不同的进程。
这类报错背后常见的原因有几处,逐个排除就行。UDP 和 TCP 是两套独立的端口空间,正常不会互相占用。另一种情况是某个进程同时用两种协议绑定,另一半失败后整体退出。
不容易想到的是,systemd 的 socket 单元已经占住了端口,服务自己再绑就冲突。还有一种情况,程序绑定地址不同,一个监听通配一个监听指定网卡,内核判定为冲突。
动手时先分别看 TCP 和 UDP 的占用情况
ss -lntup | grep ':53 '
再往下确认是不是 systemd socket 单元在占端口
systemctl list-units --type=socket | grep -E 'dns|53'
随后停掉冲突的单元再启动服务
systemctl stop dnsmasq.socket && systemctl restart named
剩下的就是验证两种协议都能响应
dig @127.0.0.1 example.com +short +tcp
恢复的判定其实很直接。ss -lntup 里 53 端口同时有 tcp 和 udp 的监听,dig 的 UDP 和 TCP 查询都能返回结果。
容易忽略的是,同端口不同协议可以共存,但同一个协议不能重复绑定;排查时用 ss 的 -u 和 -t 分开看,不要被合并输出误导。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
