Windows 端口被占用
问题的解决过程
今天碰到了一个很诡异的端口占用问题。
项目使用的端口是 9052,在启动的时候出现了下面的提示。
Description:
Web server failed to start. Port 9052 was already in use.
Action:
Identify and stop the process that's listening on port 9052 or configure this application to listen on another port.
这是一个很常见的端口占用问题,通过下面的命令就能解决了。
netstat -aon | findstr "9052"
taskkill /T /F /PID 1234
但是,在我执行 netstat -aon | findstr "9052" 之后,什么都没有输出。
奇了怪了,不应该呀。然后用 TCPView 搜索 9052 端口占用情况,也什么都没有输出。
然后我把我的问题丢给了 AI。
netstat -ano | findstr 9052 查找不到占用 9052 的应用程序,但是在启动 springboot 的时候,出现了以下提示,我应该如何排查问题? 找出占用 9052 的应用程序?
Description:
Web server failed to start. Port 9052 was already in use.
Action:
Identify and stop the process that's listening on port 9052 or configure this application to listen on another port.
AI 给了我一些的 建议
-
用管理员运行 cmd,然后再主席
netstat命令 -
使用 TCPView 软件查看
-
检查是否是被 IPv6 占用
netstat -ano -p tcp | findstr 9052
netstat -ano -p tcpv6 | findstr 9052 -
使用 PowerShell 执行下面的命令 (好使)
Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess
# 然后查看进程详情
Get-Process -Id <PID>得到下面的输出
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
2865 686 227392 34016 204.83 16184 1 Foxmail
最后查出来是 FoxMail 占用了 9052 端口。
思考
那现在的问题是为什么 netstat 没有结果输出, Get-NetTCPConnection -LocalPort 9052 却可以找到占用 9052 端口的应用呢?
我继续向 AI 追问。
为什么 netstat -ano | findstr 9052 没有结果输出,而 Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却可以找出占用 9052 端口的应用?
AI 的解释是 2 个命令的工作原理不一样。
netstat 比较老,是从 TCP/IP 协议栈的缓存中读取数据,数据不是实时的,有刷新延迟。在某些情况下,短连接或者刚建立的连接可能不会立即显示。
Get-NetTCPConnection 直接查询内核, 更准确及时。
还有一个问题,Tcpview.exe 也是从内核中读取数据,为什么当时我也没有找到呢?
继续向 AI 追问
那为什么 Tcpview.exe 没有读取到数据,Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却读到了数据?
AI 给出了几个可能的原因:
- Tcpview.exe 设置不对,如监听的协议,过滤器等设置的有问题。

- TCPView 的刷新时机问题,虽然都是从内核读取数据,但是 Tcpview.exe 还是会有刷新时间间隔的。默认是 1 秒。
- 没有以管理员权限启动 Tcpview.exe, 但是却以 管理员权限启动 PowerShell。
- 使用问题,我在搜索的时候只输入了
9052,但是 TCPView 的显示可能是*:9052. 我应该输入:9052
但是现在这个问题已无法复现了,无法得知具体是哪一个原因。只能等到后续这个问题再次出现才能知道原因了。
那么,如果这个问题再次出现,我应该如何执行什么命令,来确定它的根本问题?
继续就这个问题向 AI 追问。
由于 netstat -ano | findstr 9052 和 TCPView 查询不出数据,Get-NetTCPConnection -LocalPort 9052 | Format-Table -Property LocalAddress, LocalPort, State, OwningProcess 却可以找出占用 9052 端口的应用的问题已无法复现,那么下次这个问题再次出现,我应该执行什么命令来确定这个问题的根本原因?
AI 给我返回了一个 .ps1 文件,是的,一个 .ps1 文件,之前我从来没有接触过 ps1 的任何语法。
我粗略的看了下这个 .ps1 文件,用到的语法大概是定义变量/方法,执行方法,搭配一些 if-else 语句。
然后我给 AI 提问,让它给我介绍下这些语法。
我之前从来没接触过 ps1 脚本请向我解释 ps1 中如何定义变量,方法,如何执行方法,if-else 语句的语法。
PowerShell 脚本学习
.ps1 语法学习时间
变量
-
$name = value来定义变量 -
$arr = @("apple","banana","orange")定义数组 -
定义哈希表
$person = @{
Name = "wangzhy"
Age = 29
City = "zhuhai"
} -
定义布尔值
$isActive = $true
$isDeleted = $false -
特殊变量
$_$?$null$true$false$HOME$PSVersionTable
-
变量的使用
- 双引号内可以直接插入变量
"my name is $name"=>my name is wangzhy - 单引号内不会替换变量
'my name is $name'=>my name is $name
- 双引号内可以直接插入变量
函数
function name {
# function body
}
在函数体内通过 param($name) 获取参入的参数。默认按照参数传递顺序进行赋值,也可以指定。
function add {
param($a,$b)
Write-Host "a = $a"
Write-Host "b = $b"
return $a + $b
}
Write-Host " a + b = " (add 2 10) # a=2,b=10
Write-Host " a + b = " (add -b 2 -a 10) # a=10,b=2
给函数参数设置默认值 param($a,$b = 11) 如果没有给 b 传递值,那么 b 的默认值是 11。
条件判断
if(conditon){
} elseif(conditon) {
} else {
}
比较运算符
-
-eq -
-ne -
-gt -
-ge -
-lt -
-le -
-eq -
-ceq忽略大小写 -
-like模糊匹配 -
-math正则匹配 -
-and -
-or -
-not
三元运算符 $result = ($age -ge 18) ? "成年" : "未成年"
$() 的用途
- 用于访问对象的属性或方法
$($process.Id)执行 $process 对象的 Id 属性 - 执行复杂表达式
$($a + $b) - 命令替换
Write-Host "当前时间: $(Get-Date -Format 'HH:mm:ss')" - 嵌套属性访问
$($connection[0].LocalPort)
.ps1 脚本文件的格式要是 **UTF-8 with BOM** 的,不然的话,如果包含中文,会出现报错。
管道符 | 的使用:将左边命令的输出传递给右边命令的输入。
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5获取进程 → 排序 → 选择前 5 个123 | Set-Clipboard将 123 输出到剪贴板
最后得到一个 .ps1 文件
# ============================================
# 指定端口(通过 -port 传入,默认是 9052 端口)占用问题诊断脚本
# 当问题出现时立即运行此脚本
# ============================================
param($port = 9052)
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$logFile = "port_diagnosis_$timestamp.txt" # 日志文件
function Run-Write-Log {
param($Command)
$CommandResult = iex $Command
$Message = $CommandResult
if ($Message -isnot [string]) {
$Message = $Message | Out-String
}
Write-Host "========== $Command ==========" -ForegroundColor "GREEN"
Write-Host $Message
"========== $Command ==========" | Out-File -FilePath $logFile -Append -Encoding UTF8
$Message | Out-File -FilePath $logFile -Append -Encoding UTF8
return $CommandResult
}
$ignore = Run-Write-Log "netstat -ano | findstr :$port"
$cr = Run-Write-Log "Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue"
if ($null -ne $cr) {
# 这里要对 $($conn.OwningProcess) 去重
foreach ($conn in ($cr | Select-Object -Property OwningProcess -Unique)) {
$ignore = Run-Write-Log "Get-Process -Id $($conn.OwningProcess)"
}
}
# 通过 vscode 打开这个日志文件
code $logFile