环境: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 那你就搜搜这个词
|