环境:ubuntu22.04 go1.20
代码类似于
go func() { //开启 websocket 监听 http.HandleFunc("/", s.handler) err := http.ListenAndServe("0.0.0.0:9999", nil) if err != nil { logger.Log.Fatal(fmt.Sprintf("err=%v", err)) } }()
但是有时候启动会报错,显示err=listen tcp 0.0.0.0:9999: bind: address already in use
然而我使用netstat -tuln |grep 9999
时,却显示这个端口没被占用
于是我写一个脚本
#!/bin/bash while true; do netstat -tuln |grep 9999 sleep 0.1 done
一直开着,再写一个守护脚本当 go 进程结束时自动重启 然后我发现 go 进程因为端口占用问题已经重启了几十次,但是端口扫描的脚本却一次显示端口被占用的情况都没有
但是当我过几个小时再次重启 go 进程时,端口占用问题又消失了 这到底是怎么一回事,而且这情况不是必现的,是偶尔会出现
1 c00WKmdje2wZLrSI OP 各位大哥有没有解决的思路可以说一说 |
![]() | 2 misaka19000 2023-12-15 11:35:04 +08:00 via Android 写个其它语言的代码看看能不能监听这个端口 |
![]() | 3 daniel8642 2023-12-15 11:51:54 +08:00 0.0.0.0:9999 可以试试填写一下需要绑定到的网卡 ip 地址。 之前在 wsl2 上出现绑定之后访问不了,就是通过填写 ip 解决的。 |
![]() | 4 imherer 2023-12-15 12:00:13 +08:00 会不会是你这个函数被多次调用了? |
5 c00WKmdje2wZLrSI OP |
![]() | 6 sky96111 2023-12-15 12:21:01 +08:00 via Android https://zhaoji.wang/solve-the-problem-of-windows-10-ports-being-randomly-reserved-occupied-by-hyper-v/ 看看是不是这个问题。我经常遇到 |
7 c00WKmdje2wZLrSI OP @sky96111 不是,我是腾讯云的服务器,ubuntu22.04, 而且主要是我扫描了端口,显示未占用 |
8 zhoulq7 2023-12-15 13:16:10 +08:00 如果用了 iptables 做的端口流量转发是不能通过 netstat 查到这个被占用的端口的 |
![]() | 9 sky96111 2023-12-15 13:54:49 +08:00 via Android @c00WKmdje2wZLrSI Linux 啊,那你用 lsof -i :端口号查一下。被内核占用的端口直接是看不到的 |
10 barathrum 2023-12-15 14:11:32 +08:00 可能是 socket 还没回收,关应用的时候如果正好有链接要等 60 秒 保证被回收,没有链接的话就能直接用了。 ss 的时候去掉 l 再看看可能发现有正在关闭状态的链接。 |
11 c00WKmdje2wZLrSI OP @zhoulq7 systemctl status firewalld 和 systemctl status firewalld 显示没这两个软件 |
12 c00WKmdje2wZLrSI OP @barathrum 我换了端口后,扫描新端口没被占用,但是新端口第一次启动也有几率出现说端口被占用 |
![]() | 13 longbowape 2023-12-15 14:22:14 +08:00 需要给端口设置 SO_REUSEADDR ,否则即使进程推出了也会显示一段时间的被占用。 |
![]() | 14 Pythoner666666 2023-12-15 14:22:44 +08:00 云服务器有一些 厂商自带的扫描或者监控软件 他们可能是定时启动 端口也是 9999 ,所以可能刚好跟你冲突了。仅提供一个思路,不一定对哈。 |
15 barathrum 2023-12-15 14:26:49 +08:00 你的监控脚本换一下参数,比如 netstat -neoap 啥的,端口不一定是 listen 的。 |
![]() | 16 lsk569937453 2023-12-15 14:33:33 +08:00 https://groups.google.com/g/golang-nuts/c/nUMvimzSZvk 不知道是不是和这个有关系,用 go build 后的二进制包启动,而不是用 go run 启动进程。 |
![]() | 17 liarsa 2023-12-15 14:40:32 +08:00 我也碰到过,但没细研究,过一会它自己就好了 |
18 c00WKmdje2wZLrSI OP @lsk569937453 我使用的就是 go build 的二进制包启动的 |
![]() | 19 pkoukk 2023-12-15 18:03:48 +08:00 简单啊,你测试下换几个端口,如果还有问题就是你代码写的问题 如果没问题就是你环境的问题 |
20 mangoDB 2023-12-15 18:27:24 +08:00 netstat -n | grep TIME_WAIT |
22 julyclyde 2023-12-15 18:37:23 +08:00 if err != nil { logger.Log.Fatal(fmt.Sprintf("err=%v", err)) 请你在这里运行一下 netstat -anp 这里应该是能抓到事故现场的 } |
![]() | 23 pennai 2023-12-16 08:57:24 +08:00 你换个端口号,如果换了端口号还是同样的报错,看看是不是你写的代码有问题,这个函数跑了多次 |
![]() | 24 lifei6671 2023-12-17 11:48:32 +08:00 你可以尝试,只启动端口,不建立客户端连接,这种情况下是不是就不存在端口被占用的情况了。 如果是的话,那么可能是因为服务器端主动断开连接后,这个服务器监听的端口需要等待 2MSL 周期才能再使用。 这个时间会很短,估计在你执行 netstat 命令的时候端口已经释放了。 可以尝试缩短 TIME_WAIT 的时间,或者在关闭服务器之前,将所有客户端都 close 了再关闭服务端。 |
25 c00WKmdje2wZLrSI OP @julyclyde 感谢,抓到事故现场了,的确有进程监听了那个端口 |
26 c00WKmdje2wZLrSI OP @julyclyde 说错了,是有进程使用那个端口进行非监听状态的连接,导致我使用 netstat -tuln 找不到进程,而使用 netstat -anp 找到了 |
27 julyclyde 2023-12-18 10:20:19 +08:00 |
28 c00WKmdje2wZLrSI OP @julyclyde chatgpt 和我说的,我也不知道那是啥意思 ``` netstat -tuln | grep 9999 和 netstat -anp | grep 9999 是两个不同的命令,它们的区别在于使用的参数和显示的信息。 netstat -tuln 命令用于显示所有 TCP 和 UDP 监听的端口。它的参数含义如下: -t:仅显示 TCP 协议相关的连接。 -u:仅显示 UDP 协议相关的连接。 -l:仅显示监听状态的连接。 -n:以数字形式显示 IP 地址和端口号。 netstat -anp 命令用于显示所有活动的 TCP 和 UDP 连接。它的参数含义如下: -a:显示所有连接,包括监听和非监听状态的连接。 -n:以数字形式显示 IP 地址和端口号。 -p:显示与连接关联的进程信息。 根据你的描述,可能是因为在使用 netstat -tuln | grep 9999 命令时,没有找到与端口 9999 相关的监听状态的连接,所以没有显示结果。而使用 netstat -anp | grep 9999 命令时,显示了所有活动的连接,包括监听和非监听状态的连接,因此能够发现端口监听情况。 ``` |
29 julyclyde 2023-12-18 10:27:52 +08:00 |
30 c00WKmdje2wZLrSI OP @julyclyde ESTABLISHED |
31 julyclyde 2023-12-18 10:29:26 +08:00 @c00WKmdje2wZLrSI 那我觉得 GPT 肯定不会告诉你 ip_local_port_range 这个词 |
32 c00WKmdje2wZLrSI OP @julyclyde 是的,不会,而且我发现是另外一个进程和 mysql 通信时临时占用了端口,并且还是随机占用端口,一段时间后又释放了端口,不知道该怎么设置来避免 |
33 julyclyde 2023-12-18 20:34:17 +08:00 @c00WKmdje2wZLrSI 那你就搜搜这个词 |