云服务器端口被占用怎么办:用 ss 和 lsof 找到元凶
云服务器端口被占用怎么办:用 ss 和 lsof 找到元凶
部署服务时经常遇到 Address already in use:程序启动失败,日志里说端口被占用。下面是一套在云服务器上快速定位和释放端口的方法。
一、用 ss -lntp 定位端口
ss 是 netstat 的替代品,速度更快:
sudo ss -lntp | grep ':8080'
参数含义:-l 只看监听,-n 不解析名字,-t TCP(UDP 用 -u),-p 显示进程。输出里的 users:(("java",pid=12345,fd=88)) 就是占用者。
二、用 lsof -i 交叉确认
sudo lsof -i :8080
lsof 会列出命令名、PID、用户和连接状态(LISTEN / ESTABLISHED)。两种工具结果一致,基本就能确定元凶。注意不加 sudo 可能看不到其他用户的进程。
三、查清进程从哪来
拿到 PID 后,先弄清它是谁启动的,避免杀了又被拉起来:
ps -fp 12345 # 看完整命令行和父进程
systemctl status 12345 # 看是否属于某个 systemd 服务
sudo docker ps --format '{{.Names}} {{.Ports}}' # 看是否是容器映射的端口
如果是 docker-proxy 占着端口,说明某个容器做了端口映射,应该处理容器而不是进程。
四、正确释放端口
按从温和到强硬的顺序:
sudo systemctl stop myapp # 属于服务的,用服务管理停止
sudo docker stop 容器名 # 属于容器的
kill 12345 # 普通进程先发 SIGTERM,让它优雅退出
sleep 5; kill -9 12345 # 仍不退出再用 SIGKILL
直接 kill -9 会让程序来不及清理临时文件和连接,能不用就不用。若服务设置了开机自启而你不再需要,记得 systemctl disable。
五、TIME_WAIT 造成的"假占用"
有时进程已经退出,ss -tan | grep 8080 却看到一堆 TIME_WAIT,新程序依然绑定失败。这是 TCP 正常的连接收尾状态,通常一两分钟后消失。根本解决是让服务端程序在 bind 前设置 SO_REUSEADDR:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
主流框架(Nginx、Go net/http、Node 等)默认已开启,自己写的小服务要留意。
小结
端口被占用时:ss -lntp 定位、lsof -i 确认、ps/systemctl/docker ps 查来源,再按 stop → kill → kill -9 的顺序释放;遇到 TIME_WAIT 不要慌,等一会或打开 SO_REUSEADDR 即可。
- 点赞
- 收藏
- 关注作者
评论(0)