---
title: Linux:用 ss 查端口与连接(默认视野、协议与数字开关、进程与权限、五列、连接状态、过滤、实战)
date: 2026-10-24
description: ss 读内核套接字表而非主动探测、默认只显示已建立连接(-l/-a)、-t/-u 选协议与 -n 不解析服务名(约定名不等于事实)、-p 进程与 sudo 权限、五列与监听行的队列含义(backlog)、ESTAB/CLOSE-WAIT/TIME-WAIT 三个状态、sport/dport 过滤、实战查端口占用与"查不到不等于没有"
tags: [Linux, 网络基础, ss, 端口, 套接字, TCP状态]
---
# Linux:用 ss 查端口与连接
## 笔记区
> 📌 GitHub:https://github.com/AR-firefly
### 点 1:`ss` 是什么
**场景**:本机有两个不认识的端口在听(`127.0.0.1:6099`、`127.0.0.1:6185`),要查它们是谁、什么状态。
**`ss` = socket statistics(套接字统计)**。做的只有一件事:问内核「现在有哪些套接字、什么状态」,把内核的答案打印出来。
- 套接字:内核账本里的一行登记,记录「哪个 IP、哪个端口、什么协议、现在什么状态、归哪个进程」。
- `ss` **不去网络上探测**:不发包、不主动建连接,只读内核已有的账。
- 替代 `netstat`(老工具,本机没装);与 `ip` 命令同属 `iproute2` 软件包。
**原文**(Linux Journey `troubleshooting/netstat`):
> **英文原句**:The legacy `netstat` tool displays sockets, routes, and interface statistics. On modern Linux, `ss` is the preferred socket-inspection tool because it exposes kernel socket state efficiently and is maintained with iproute2.
> **中文翻译**:传统的 `netstat` 工具显示套接字、路由和接口统计。在现代 Linux 上,`ss` 是首选的套接字检查工具,因为它能高效地暴露内核套接字状态,并且随 iproute2 维护。
> **说人话**:`netstat` 是老工具;现在用 `ss`,它直接读内核的账,快,而且一直在更新。
「读的是内核的数据,只问有哪些套接字,套接字是什么状态,别的都不干,不去网络上探测」。
**边界**:
- `ss` 能看到**内核账本里已有的条目**,连接的两端(含对方 IP)都在账里,所以看得到。
- 看不到的是**账本里根本没有的东西**——例如"8.8.8.8 通不通",那是没发生的连接,内核没有这条记录,`ss` 也不会主动去连。
- 分界线是**有没有这条记录**,不是"本地还是外来"。
### 点 2:默认视野——为什么敲 `ss` 看不到监听
**实际现象**:不加选项的 `ss`,输出里**一行 `LISTEN` 都没有**。
**`man 8 ss` 原文**:
> **英文原句**:When no option is used ss displays a list of open non-listening sockets (e.g. TCP/UNIX/UDP) that have established connections.
> **中文翻译**:不带任何选项时,`ss` 显示的是开放的、非监听的套接字(例如 TCP/UNIX/UDP)里已经建立连接的那些。
> **说人话**:`ss` 默认只给看「已经连上的」,光在等客人的那些(监听)默认不显示。
**三个词**:
- **`LISTEN`**:状态名,表示这个套接字在等别人来连。
- **`-l`**(listen):只看监听。
- **`-a`**(all):监听 + 非监听都要。
**监听**:程序已经占住端口、内核给它记一条「这个端口有人管」,坐在那儿等别人来连;还没人连进来,状态就是 `LISTEN`。店面已开门、柜台有人、客人未到——就是 `LISTEN`;客人进门开始说话,状态才变成 `ESTAB`。
**实测**:
- `ss`:`LISTEN` 行 **0** 行(本机实测)
- `ss -a`:`LISTEN` 行 **77** 行(含大量 UNIX 套接字)
「直接敲ss返回的是默认的视野,只给已经连上的,当然没有listen的了」。
**考点结论**:默认输出里没有 `LISTEN`,**不能当"本机没有服务在监听"的证据**。
### 点 3:`-t` / `-u` 选协议,`-n` 不解析名字
**Linux Journey 原文**:
> **英文原句**:`-l` selects listeners, `-n` avoids name lookup, `-t` and `-u` select TCP and UDP, and `-p` requests process data. UDP is connectionless, so its unconnected bound sockets do not have TCP-style `LISTEN` handshakes.
> **中文翻译**:`-l` 选择监听器,`-n` 避免名称查询,`-t` 和 `-u` 分别选择 TCP 与 UDP,`-p` 请求进程数据。UDP 是无连接协议,所以它未连接的、已绑定的套接字没有 TCP 那样的 `LISTEN` 握手。
> **说人话**:`-t` = 只要 TCP,`-u` = 只要 UDP,`-n` = 别把数字翻译成名字。UDP 没有"连接"这回事,它的监听行不叫 `LISTEN`,叫 `UNCONN`。
**`-n` 的差别**:端口 53 的约定名是 `domain`。
- 不带 `-n`:显示 `:domain`
- 带 `-n`:显示 `:53`
**为什么排障要用 `-n`**(Linux Journey 原文):
> **英文原句**:`/etc/services` maps conventional names to numbers, but it does not prove which process currently owns a port or which application protocol it speaks.
> **中文翻译**:`/etc/services` 把约定俗成的名字映射到数字,但它不能证明当前哪个进程占着这个端口,也不能证明它说的是哪种应用层协议。
> **说人话**:那是一本"号码本"——53 约定叫 `domain`、443 约定叫 `https`,`ss` 只是替用户去查了这本号码本。**名字是登记的名字,不是这台机器上正在发生的事。**
本机核对:`getent services domain` → `domain 53/tcp`;`getent services 443` → `https 443/tcp`。
**实测**:`ss -lu` 显示 `UNCONN … :domain`;加 `-n` 后变成 `:53`。
### 点 4:`-p` 看进程,以及为什么常在 `sudo` 后面
**Linux Journey 原文**:
> **英文原句**:Show listening TCP and UDP sockets numerically, including owning processes when permitted.
> **中文翻译**:以数字形式显示监听中的 TCP 与 UDP 套接字,并在权限允许时包含所属进程。
> **说人话**:`-p` 让 `ss` 多报一列"谁在用";给不给看,取决于有没有权限。
**`man 8 ss`**:`-p, --processes` —— `Show processes using sockets.`
- `-p` 加一列 `Process`,格式:`users:(("程序名",pid=数字,fd=数字))`。
- **不加 `sudo`** 时,别的用户的进程信息看不到,`Process` 列常为**空**——不是没有进程,是没权限看。
- 加 `sudo` 以 root 身份问,整列才出来。
**实测**:
- `ss -lntp`(无 sudo):`Process` 列全空
- `sudo ss -lntup`:出现 `users:(("systemd-resolve",pid=79,fd=18))`
**现象记录**:即使加了 `sudo`,`10.255.255.254:53` 和 `127.0.0.1:323` 的部分行 `Process` 仍为空——说明 `ss` 也有"套接字在、但关联不到进程"的情况;确切原因未核到,只记现象。
「空可能表明你没权限,sudo看了确实为空才可能是真的没进程」。
**补充词**:`fd` = 文件描述符,进程打开一个套接字时内核发给它的编号;一个程序可同时开多个套接字,所以同一个程序会有多行、`fd` 不同。
### 点 5:五列怎么读
| 列 | 是什么 |
| -------------------- | ----------------------------------------------------------------- |
| `State` | 状态:`LISTEN`(在等)、`UNCONN`(UDP 已绑定)、`ESTAB`(已连接) |
| `Recv-Q` | 接收队列 |
| `Send-Q` | 发送队列 |
| `Local Address:Port` | 本机:哪个 IP、哪个端口 |
| `Peer Address:Port` | 对面:哪个 IP、哪个端口 |
**Linux Journey 对队列的原文**:
> **英文原句**:`Recv-Q` and `Send-Q` meanings depend on state and protocol. On established TCP sockets they can indicate data queued for application receipt or transmission acknowledgement. On listening sockets, queue fields describe connection backlog state rather than application payload bytes in the same way.
> **中文翻译**:`Recv-Q` 和 `Send-Q` 的含义取决于状态和协议。在已建立的 TCP 套接字上,它们可以表示等待应用接收、或等待发送确认的数据。在监听套接字上,队列字段描述的是连接积压状态,而不是同样意义上的应用负载字节。
> **说人话**:这两列的意思会变。连上之后是"多少数据还堵着";还没人连的监听行,是"还有多少个连接请求在排队"。
**监听行的两格**:
- `Recv-Q` = 已完成握手、等程序接管(accept)的连接数——本机 `0`
- `Send-Q` = 这个监听队列最多能排多长——本机 `4096`,与 `/proc/sys/net/core/somaxconn`(4096)一致;`1000` 那行是程序自己设的值
**`0.0.0.0` 的两个位置**:
- `Local` 的 `0.0.0.0`:任意本机地址都接——主动的选择
- `Peer` 的 `0.0.0.0:*`:还没有对端(监听时没人连)——占位符
### 点 6:三个连接状态
**Linux Journey 原文**:
> **英文原句**:`ESTAB`: the TCP connection is established. / `CLOSE-WAIT`: the peer closed its sending side, but the local application has not closed its socket. / `TIME-WAIT`: the endpoint that actively closed waits so delayed segments expire and the final exchange can be handled safely.
> **中文翻译**:`ESTAB`:TCP 连接已建立。/`CLOSE-WAIT`:对端关闭了它的发送方向,但本地应用程序尚未关闭套接字。/`TIME-WAIT`:主动关闭的一端在等待,以便延迟报文过期,并让最后的交换被安全处理。
> **说人话**:`ESTAB` = 连上了、正常说话;`CLOSE-WAIT` = 对方说完了、关了,本机程序还没关;`TIME-WAIT` = 主动关闭的那一方先关,关完得等一会儿,让路上迷路的包过期。
**时间顺序**:`ESTAB`(双方都开着)→ 一方先关 → 另一方 `CLOSE-WAIT`(收到 FIN,等程序关);先关的那方 `TIME-WAIT`(等残留报文过期)。
**两个运维结论**:
- `CLOSE-WAIT` 堆积:不是网络问题,是**本地程序没关套接字**——收到对方 FIN,但代码没 `close()`;堆太多会吃光文件描述符。
- `TIME-WAIT`:协议要求的正常状态,不是故障;只有数量过多、影响端口资源时才值得处理。
**FIN** = TCP 报文头里的标志位,表示「本端不再发数据了」,是关闭方向的第一步。
**实测**:`ss -tan state time-wait` → 0 行;`ss -tan state listening` → 3 行。
**参数格式坑**:输出里显示 `ESTAB`(缩写),但 `state` 过滤要写小写全名 `established`;写 `ESTAB` 会报 `wrong state name: ESTAB`(本机实测)。
### 点 7:过滤——按状态、按端口
**`man 8 ss` 原文**:
> **英文原句**:`{dport|sport} [OP] [FAMILY:]:PORT` — Compare the destination or source port to PORT. OP can be any of `<`, `<=`, `=`, `!=`, `>=`, and `>`, following normal arithmetic rules.
> **中文翻译**:`dport` 或 `sport` 后跟比较符和端口,用来比较目的端口或源端口。比较符可以是小于、小于等于、等于、不等于、大于等于、大于,遵循普通算术规则。
> **说人话**:`sport` 看本机这一端的端口,`dport` 看对端的端口;中间写比较符,后面写端口。
**两个细节**:
- 冒号:`sport = :443` 里冒号前面是 IP,空着 = 任意 IP;也可写 `sport = 127.0.0.1:443`。
- 引号:整个条件习惯加单引号——`<`、`>` 是 shell 的重定向符号,不加引号会被 shell 先吃掉(实测 `=` 不加没事,`<` `>` 不行,一律加最省心)。
**`sport` vs `dport`**:
- `sport` = 本机这一端的端口(看本机开了哪些服务)
- `dport` = 对端的端口(看本机连别人哪个端口)
**实测**:
- `ss -ltn 'sport = :53'` → 3 行,`Local` 全是 `:53`
- `ss -lun 'sport = :323'` → 4 行
- `ss -nt 'dport = :22'` → 空(本机没有已建立的外部 22 连接)
### 点 8:实战——查 53 端口被谁占着
**现象**:本机 53 端口在听,怀疑不是系统自带的东西。
**计划**:「全敲,因为记不住 TCP 和 UDP,然后指定 53 」——不限定协议(两种都看),再用端口钉死。
**第一次**:`ss -ltnu 'sport = :53'`(没有 `-p`)
结果:UDP 3 行 + TCP 3 行,绑了 `127.0.0.54`、`127.0.0.53%lo`、`10.255.255.254` 三个地址;**但没有 `Process` 列**——因为命令里没带 `-p`。
**第二次**:`sudo ss -ltnup 'sport = :53'`
结果:`users:(("systemd-resolve",pid=79,fd=18))` —— 占用者是 `systemd-resolve`,**TCP 和 UDP 两种协议都占**(看 `Netid` 列)。
**`Netid`** = 网络协议标识,这一行属于 `tcp` / `udp` / `unix` 哪一种。
**考点结论**:用 `ss -ltn` 查不到某个端口,**不能断定没有程序在用它**——`-t` 只看了 TCP(UDP 没看),`-l` 只看监听(已建立的连接也会占着本地端口)。
## 线索区(学完后合上材料,自问自答)
**Q: `ss` 的数据从哪来?它会不会主动去网络上探测?**
A: 读内核维护的套接字表;不会发包、不会主动建连接。所以"没连上过的目标"它看不到——不是"外来东西"看不到,而是内核账本里没有那条记录。
**Q: 不加任何选项的 `ss` 显示什么?想看到监听要加哪个字母?**
A: 只显示已建立连接的非监听套接字(`man 8 ss` 第一段),监听默认藏起来。`-l` 只看监听,`-a` 两种都要。
**Q: 为什么排障要用 `-n`?**
A: 不加 `-n` 会把端口数字翻译成 `/etc/services` 里的约定名(53 → `domain`)。名字是约定,不证明谁占着端口、跑什么协议;`-n` 看的是内核里的真数字。
**Q: `-p` 不加 `sudo` 会怎样?**
A: `Process` 列空——不是没有进程,是没权限看别人的进程信息。空列不能当"没有进程"的证据,加 `sudo` 再确认。
**Q: 监听行的 `Recv-Q` / `Send-Q` 是什么意思?和已连接行一样吗?**
A: 不一样。监听行:`Recv-Q` = 已完成握手、等程序接管(accept)的连接数;`Send-Q` = 队列上限(本机 4096,与 `/proc/sys/net/core/somaxconn` 一致)。已连接行才是"等着取/等着发"的数据量。
**Q: `CLOSE-WAIT` 是哪一方还没关?`TIME-WAIT` 呢?**
A: `CLOSE-WAIT` = 对端已发 FIN、本地程序还没 `close()`(所以堆积要查本机程序)。`TIME-WAIT` = 主动关闭的一方等残留报文过期,双方都关了,属正常状态。
**Q: `sport` 和 `dport` 各看哪一端?**
A: `sport` 看本机这一端的端口,`dport` 看对端的端口。`state` 过滤要写小写全名(`established`),输出里却显示缩写(`ESTAB`)。
**Q: 用 `ss -ltn 'sport = :8080'` 查不到,能不能断定没有程序占 8080?**
A: 不能。`-t` 只看了 TCP(UDP 没看)、`-l` 只看监听(已建立连接也会占本地端口);要扩范围再确认。
## 总结(50字以内)
`ss` 读内核套接字表;默认只看已连接的,监听要 `-l`/`-a`;`-n` 看真数字不被名字骗;`-p` 看进程要 `sudo`;查不到不等于没有。
## 复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| --------------------------- | --------- | -------------------------------------------- | ------------------ |
| `ss` | 必学 | socket statistics;读内核套接字表 | 查端口与连接 |
| `ss` 不探测 | 必学 | 不发包,只看内核已有的账 | 判断"查不到"的含义 |
| 默认视野 | 必学 | 只显示已建立连接的非监听套接字 | 为什么没有 LISTEN |
| `-l` / `-a` | 必学 | listen / all | 看监听 |
| `LISTEN` | 必学 | 端口开着、等别人连 | 判断服务在不在 |
| `-t` / `-u` | 必学 | tcp / udp | 筛协议 |
| `-n` | 必学 | numeric,不解析服务名 | 看真数字 |
| `UNCONN` | 必学 | UDP 已绑定、无连接 | 看 UDP 监听 |
| `/etc/services` | 不记 | 名字↔端口约定表;`man 5 services` | 为什么名字不算证据 |
| `-p` | 必学 | process,显示占用进程 | 查谁占端口 |
| `sudo` 与 `-p` | 必学 | 没权限时 Process 列为空 | 空列不等于没进程 |
| `users:(("名",pid=N,fd=N))` | 必学 | 进程名 + 进程号 + 文件描述符 | 读占用行 |
| `fd` | 不记 | 文件描述符;`man 7 socket` | 一个程序多行 |
| `Netid` | 不记 | 协议列:tcp/udp/unix | 读输出 |
| `Recv-Q` / `Send-Q` | 了解 | 含义随状态变;监听行是 backlog | 队列读法 |
| `backlog` / `somaxconn` | 了解 | 监听队列上限;`/proc/sys/net/core/somaxconn` | 队列上限 |
| `Local Address:Port` | 必学 | 本机 IP 与端口 | 读一行 |
| `Peer Address:Port` | 必学 | 对端 IP 与端口 | 读一行 |
| `0.0.0.0` | 必学 | 任意本机地址;Peer 位是占位符 | 两个位置区别 |
| `ESTAB` | 必学 | established,已连接 | 看活动连接 |
| `CLOSE-WAIT` | 必学 | 对端关了、本地程序没关 | 查程序是否漏 close |
| `TIME-WAIT` | 必学 | 主动关闭方等残留报文过期 | 正常状态 |
| `FIN` | 必学 | 关闭方向的标志位 | 理解关闭流程 |
| `state` 过滤 | 必学 | 按状态筛;写小写全名 | 只看某状态 |
| `sport` / `dport` | 必学 | 本机端口 / 对端端口 | 钉住某条 |
| `-s` `-e` `-o` `-m` | 不记 | 汇总/扩展/定时器/内存;`man 8 ss` | 锚点 |
## 流程附加段
### 旧知识回收
| 概念 | 一句话 | 出处 |
| ------------- | --------------------------------------------------------------- | ------------------------------------------------------------- |
| 监听的语义 | 端口占住了、在等别人连,但还没人连 | 点 2 讲完后用户问"什么叫监听",当场补 |
| TCP vs UDP | TCP 有连接/可靠/有序/字节流;UDP 无连接/不保证/保留边界 | 点 4 讲解时用户说记不得,当场补并写成对比表(用户要求进笔记) |
| 套接字 | 内核账本里的一行;一个 TCP 连接由两个套接字组成 | 点 6 讲 `CLOSE-WAIT` 时用户要求再讲一遍 |
| `-t` 三种含义 | `logger -t` 标签 / `journalctl -t` 筛标签 / `dmesg -t` 去时间戳 | 复习抽考第 3 问先说不知道,补讲后答对 |
### TCP 与 UDP 对比
| 维度 | TCP | UDP |
| ------------- | ----------------------------------------------- | ---------------------------- |
| 连接 | 先三次握手,建好才发 | 不建连接,直接发 |
| 可靠 | 确认 + 重传,尽量送到 | 不保证送达 |
| 顺序 | 保证按序 | 不保证 |
| 边界 | 字节流,不保留分界 | 保留每条数据报的分界 |
| 常见用途 | 网页、SSH、数据库 | DNS、视频、游戏、时间同步 |
| `ss` 里的状态 | `LISTEN` / `ESTAB` / `CLOSE-WAIT` / `TIME-WAIT` | `UNCONN`(没有连接状态可看) |
### 今日产出验收
| 产出项 | 回答 | 判定 |
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---- |
| 用 `sudo ss -lntup` 查出一个端口被谁占着 | 命令 `sudo ss -ltnup 'sport = :53'`,输出 `users:(("systemd-resolve",pid=79,fd=18))`,并指出 TCP/UDP 两种协议都占 | ✅ |
| 说清 `ESTAB` / `CLOSE-WAIT` / `TIME-WAIT` 三个状态 | 「CLOSE-WAIT是对面关了用户没关」;记法:「左边是对方,右边是用户,对方关了然后在等,而用户没关」 | ✅ |
| 说清 `Recv-Q` / `Send-Q` 在监听套接字上表示什么(了解层) | 「0代表握手结束了,4096代表最多能排多少个队伍」 | ✅ |
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2503_94114317/article/details/169170365



