在使用 IntelliJ IDEA 等工具做 Java 开发时,偶尔会遇到 IDEA 中已经停止应用实例,但是重启启动的时候提示端口已经被占用。虽然可以改个端口启动,或者手动找到对应进程干掉,但是总是麻烦又恼人,因此撸一个脚本用来快速处理该场景问题。
以下为 Windows、macOS、Linux 三个系统通过端口号获取 PID 并终止进程的完整解决方案文档,综合了多平台特性与安全性设计:
一、Windows 系统
实现脚本
@echo off
chcp 65001 >nul && cls
REM 确保控制台使用 UTF-8 编码(需配合支持 Unicode 的字体,如 "Lucida Console")
setlocal enabledelayedexpansion
REM 脚本功能:终止占用指定端口的进程(支持多端口,无参数时使用默认端口列表)
REM 默认端口:8080 9001
REM 使用示例:kill_ports.bat 8080 9001
REM 自动请求管理员权限(可选)
NET FILE >nul 2>&1
if %errorlevel% neq 0 (
echo 正在请求管理员权限...
powershell Start-Process "%~0" %* -Verb RunAs
exit /b
)
REM 设置默认端口列表
set "default_ports=8080 9001"
set "ports=%*"
REM 如果入参为空,使用默认端口
if "!ports!"=="" (
set "ports=!default_ports!"
echo 未提供端口参数,使用默认列表:!ports!
)
REM 遍历所有端口(用户输入或默认)
for %%p in (!ports!) do (
set "port=%%p"
echo 正在检查端口: !port! ...
REM 查找占用端口的 PID
set "pid_list="
for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":!port! " ^| findstr "LISTENING"') do (
set "pid=%%a"
set "pid_list=!pid_list! !pid!"
)
REM 终止进程
if defined pid_list (
echo 发现进程 PID: !pid_list!
for %%i in (!pid_list!) do (
taskkill /F /PID %%i >nul 2>&1
if !errorlevel! equ 0 (
echo [成功] 端口 !port! 的进程 PID:%%i 已终止
) else (
echo [失败] 端口 !port! 的进程 PID:%%i 终止失败(可能需要管理员权限)
)
)
) else (
echo 未找到占用端口 !port! 的进程
)
echo -------------------------------
)
endlocal
pause
特性说明
- 自动提权:通过 PowerShell 请求管理员权限,避免权限不足问题
- 多端口支持:支持命令行参数输入或默认端口列表(8080,9001)
- 精准匹配:使用
netstat
过滤 LISTENING 状态的端口进程 - 结果反馈:明确标注终止成功/失败状态,提示权限问题
二、macOS 系统
实现脚本
#!/bin/zsh
# 默认端口列表
default_ports=(8080 9001)
ports=(${@:-${default_ports[@]}})
# 权限检查
if [[ $EUID -ne 0 ]]; then
echo "检测到非 root 权限,部分进程可能需要 sudo 执行"
fi
# 遍历端口终止进程
for port in ${ports[@]}; do
echo "检查端口: $port"
pids=$(lsof -ti :$port | tr '\n' ' ')
if [[ -n "$pids" ]]; then
echo "发现进程 PID: $pids"
for pid in ${pids[@]}; do
kill -9 $pid 2>/dev/null
if [[ $? -eq 0 ]]; then
echo "[成功] 端口 $port 进程 PID:$pid 已终止"
else
echo "[失败] 端口 $port 进程 PID:$pid 终止失败(尝试 sudo 执行)"
fi
done
else
echo "端口 $port 无进程占用"
fi
echo "------------------------------"
done
特性说明
- 动态参数处理:支持命令行输入或默认端口列表
- 权限检测:提示非 root 用户可能存在的权限限制
- 精确查找:通过
lsof -ti
获取精确 PID 列表 - 批量处理:支持同一端口多个进程的终止操作
- 错误隔离:独立处理每个 PID 的终止结果
三、Linux 系统
实现脚本
#!/bin/bash
# 默认端口列表
default_ports=(8080 9001)
ports=("${@:-${default_ports[@]}}")
# 权限检查
if [[ $EUID -ne 0 ]]; then
echo "提示:部分进程可能需要 sudo 权限终止"
fi
# 遍历端口终止进程
for port in "${ports[@]}"; do
echo "检查端口: $port"
pids=$(ss -ltnpu | awk -v port=":$port$" '$5 ~ port {split($6,a,"=");print a[2]}' | uniq)
# 备用方案(若 ss 不可用)
[[ -z "$pids" ]] && pids=$(lsof -ti :$port)
if [[ -n "$pids" ]]; then
echo "发现进程 PID: $pids"
for pid in ${pids}; do
kill -9 $pid 2>/dev/null
if [[ $? -eq 0 ]]; then
echo "[成功] 端口 $port 进程 PID:$pid 已终止"
else
sudo kill -9 $pid 2>/dev/null
[[ $? -eq 0 ]] && echo "[sudo 成功] 端口 $port 进程终止" || echo "[致命错误] 进程 $pid 终止失败"
fi
done
else
echo "端口 $port 无进程占用"
fi
echo "------------------------------"
done
特性说明
- 双引擎检测:优先使用
ss
命令获取进程信息,兼容性更强 - 自动降级:当
ss
不可用时回退到lsof
方案 - 智能提权:普通用户首次尝试失败后自动使用 sudo 重试
- 进程关联:通过
ss
提取的 PID 包含套接字关联进程 - 错误分级:区分普通错误与需管理员干预的致命错误
四、跨平台共性设计
- 默认端口机制:均支持 8080 和 9001 默认端口
- 输入扩展性:支持通过命令行参数指定任意端口
- 状态反馈:统一采用分级状态标识(成功/失败/警告)
- 日志友好:使用分隔符
------------------------------
增强可读性 - 错误抑制:
2>/dev/null
抑制非必要系统报错
五、使用示例
# Windows
kill_ports.bat 3000 8081
# macOS/Linux
chmod +x kill_ports.sh
./kill_ports.sh 3000 8081
评论区