现代linux系统更倾向于使用ss命令,因其通过netlink直接与内核通信,性能更高、信息更全、支持精细过滤,尤其在处理大量连接时远优于依赖解析/proc文件的netstat。
在linux系统中,要查看当前系统开放或正在使用的端口,最常用的两个命令是
ss
和
netstat
。它们都能提供端口的监听状态、已建立的连接以及相关的进程信息。虽然
netstat
是老牌工具,但在现代Linux发行版中,
ss
因其更高的效率和更丰富的功能,正逐渐成为首选。
解决方案
要查看Linux中的端口,我们可以利用
ss
或
netstat
命令配合不同的参数。
使用
ss
命令:
ss
命令是
socket statistics
的缩写,它能直接从内核获取套接字信息,因此在处理大量连接时,通常比
netstat
更快。
-
查看所有监听的TCP和udp端口(数字格式):
ss -tuln
这里
-t
表示TCP,
-u
表示UDP,
-l
表示监听状态,
-n
表示以数字形式显示端口号和IP地址,而不是尝试解析服务名或主机名。这是我个人最常用的组合,能快速概览哪些服务在等待连接。
-
查看所有已建立的TCP连接:
ss -tna
-a
显示所有(监听和非监听)套接字。
-
查看所有连接及其关联的进程信息:
ss -apn
-p
会显示拥有该套接字的进程名和PID。这在排查哪个程序占用了某个端口时非常有用。
使用
netstat
命令:
netstat
(network statistics)也是一个功能强大的网络工具,但它通过解析
/proc/net
目录下的文件来获取信息,在大连接量下可能会显得有些慢。
-
查看所有监听的TCP和UDP端口(数字格式):
netstat -tuln
参数含义与
ss
命令类似。
-
查看所有连接及其关联的进程信息:
netstat -apn
同样,
-p
参数用于显示进程信息。
-
查看所有TCP连接的详细信息:
netstat -ant
这里的
-a
表示所有连接,
-n
表示数字显示,
-t
表示TCP协议。
通常,我会优先使用
ss
,因为它在性能上的优势是实实在在的。但如果我面对的是一个较老的系统,或者习惯性地敲下了
netstat
,它也一样能完成任务。
为什么现代Linux系统更倾向于使用
ss
ss
命令来查看网络连接?
现代Linux系统之所以更推荐使用
ss
而非
netstat
,核心原因在于它们的底层实现机制差异巨大。
netstat
的历史可以追溯到很久以前,它主要通过读取
/proc/net/tcp
、
/proc/net/udp
等文本文件来获取网络连接信息。这种方式在连接数量不多时尚可接受,但当系统上有成千上万个连接(比如一个繁忙的Web服务器或数据库服务器)时,解析这些庞大的文本文件会变得非常低效,甚至可能导致命令执行缓慢,占用大量CPU资源。我记得有一次在生产环境排查一个连接泄漏问题,
netstat
跑起来简直是煎熬,命令行卡了半天,而
ss
几乎是秒出结果,那一刻真是体会到什么叫“现代工具”的优势。
相比之下,
ss
命令直接利用了Linux内核提供的
netlink
套接字机制。
netlink
是一种更高效的内核与用户空间通信方式,它允许
ss
直接向内核查询网络统计信息,避免了文件解析的开销。这使得
ss
在以下几个方面表现出显著优势:
- 性能卓越: 对于大量并发连接的系统,
ss
的执行速度远超
netstat
,能够更快地返回结果,极大地提高了故障排查效率。
- 信息更丰富:
ss
能够提供比
netstat
更详细的TCP连接状态信息,比如TCP窗口大小(
wscale
)、缓冲区大小(
sk_rmem
、
sk_wmem
)、TCP状态机定时器信息(
timer
)、RTT(往返时间)等。这些额外的信息对于深入分析网络性能问题和诊断疑难杂症非常有帮助。
- 功能更强大:
ss
支持更复杂的过滤和查询条件,例如可以根据TCP状态、源/目的地址、端口范围等进行精细化过滤,这让查找特定连接变得更加便捷。
所以,虽然
netstat
依然可用,但在追求效率和深度分析的场景下,
ss
无疑是更优的选择。很多Linux发行版甚至已经将
netstat
标记为“过时”,推荐用户转向
ss
。
如何使用
ss
ss
或
netstat
命令过滤和查找特定的端口连接?
在实际操作中,我们很少需要查看所有的端口信息,更多时候是想找到特定端口、特定状态或特定程序的连接。
ss
和
netstat
都提供了强大的过滤能力。
过滤特定端口:
最直接的方法就是结合
grep
命令。
- 查找监听在80端口的TCP服务:
ss -tuln | grep ':80'
或者使用
netstat
:
netstat -tuln | grep ':80'
- 查找与ssh(22端口)相关的连接:
ss -ant | grep ':22'
这里
-a
显示所有连接,
-n
数字显示,
-t
只显示TCP。
过滤特定状态:
ss
命令可以直接通过
state
关键字进行状态过滤,这比
netstat
结合
grep
效率更高。
- 查找所有处于
ESTABLISHED
(已建立)状态的TCP连接:
ss -tn state established
- 查找所有处于
LISTEN
(监听)状态的TCP连接:
ss -tn state listening
- 查找所有处于
TIME-WaiT
状态的连接(这对于诊断高并发服务器上的连接资源耗尽问题很有用):
ss -tn state time-wait
netstat
通常需要先列出所有连接,再通过
grep
过滤状态,效率稍低:
netstat -ant | grep ESTABLISHED
过滤特定协议:
- 只看TCP连接:
ss -tln
或
netstat -tln
- 只看UDP连接:
ss -uln
或
netstat -uln
过滤特定程序或PID:
使用
-p
参数可以显示拥有该套接字的进程信息。
- 查找所有由
sshd
服务打开的连接:
ss -apn | grep sshd
或者查找占用某个特定端口的进程,比如80端口:
ss -apn | grep ':80'
输出会包含进程名和PID,例如
users:(("nginx",pid=1234,fd=5))
。这里有个小技巧,有时候你发现一个端口被占用了,但不知道是哪个程序,
ss -apn
或者
netstat -apn
就能直接告诉你PID和程序名,非常方便。我经常用它来揪出那些“幽灵进程”,比如一个服务崩溃后,它的监听端口可能还被一个僵尸进程或者旧的实例占用着。
通过这些组合和过滤,我们可以非常精确地定位到我们关心的网络连接信息,大大提升了排查问题的效率。
理解
ss
ss
和
netstat
输出中的端口状态和关键信息
掌握了如何使用命令,下一步就是理解它们输出的信息,特别是那些看似神秘的端口状态。这些状态是TCP/IP协议栈内部连接生命周期的体现,理解它们对于网络故障诊断至关重要。
常见的TCP端口状态及其含义:
- LISTEN (监听): 服务器端程序正在等待客户端连接。端口已打开,并准备接受传入连接。
- SYN_SENT (同步已发送): 客户端已发送一个SYN(同步)报文请求建立连接,正在等待服务器的SYN/ACK(同步/确认)响应。
- SYN_RECV (同步已接收): 服务器已收到客户端的SYN报文,并已发送自己的SYN/ACK报文,正在等待客户端的ACK(确认)报文。
- ESTABLISHED (已建立): TCP连接已经成功建立,双方可以开始进行数据传输。这是最常见的活动连接状态。
- FIN_WAIT1 (终止等待1): 应用程序已请求关闭连接,并发送了FIN(终止)报文,等待对端的ACK。
- FIN_WAIT2 (终止等待2): 已收到对端的ACK,现在等待对端发送FIN报文来关闭连接。
- TIME_WAIT (时间等待): 连接已关闭,但本地套接字仍在等待一段时间,以确保所有迟到的报文段都已在网络中消失。这是TCP连接关闭的最后一个阶段,通常持续2MSL(Maximum Segment Lifetime,最大报文段生存时间)。大量
TIME_WAIT
连接可能导致端口资源耗尽,影响新连接的建立。
- CLOSE_WAIT (关闭等待): 对端已发送FIN报文并关闭了连接,但本地应用程序尚未关闭其套接字。这通常意味着本地应用程序在处理完剩余数据后,需要主动关闭连接。
- LAST_ACK (最后确认): 本地应用程序已发送FIN报文并收到对端的FIN报文,现在正在等待对端的ACK报文来确认本地的FIN。
- CLOSING (关闭中): 双方同时发送了FIN报文,但本地在收到对端的FIN之前收到了自己的FIN的ACK。这种情况比较少见。
ss
和
netstat
输出中的关键字段:
- Proto (协议): 指示是TCP还是UDP协议。
- Recv-Q / Send-Q (接收队列/发送队列):
- 对于
netstat
,通常表示在套接字缓冲区中等待发送或接收的字节数。
- 对于
ss
,在
ESTABLISHED
状态下,
Recv-Q
表示接收队列中未被应用程序读取的字节数,
Send-Q
表示发送队列中未被远程主机确认的字节数。在
LISTEN
状态下,它们可能表示待处理的(未完成三次握手)和已完成三次握手的连接数。
- 对于
- Local Address:Port (本地地址:端口): 本地机器的IP地址和端口号。
0.0.0.0
表示监听所有可用的IP地址,
::
表示监听所有IPv6地址。
- Foreign Address:Port (外部地址:端口): 远程机器的IP地址和端口号。
- State (状态): 上面解释的TCP连接状态。
- PID/Program name (进程ID/程序名): 拥有该套接字的进程ID和对应的程序名称。
这些状态看似复杂,但理解了它们,你就能更好地诊断网络问题。比如,如果看到大量
TIME_WAIT
,可能需要调整系统参数(如
net.ipv4.tcp_tw_reuse
或
net.ipv4.tcp_tw_recycle
,尽管后者在某些场景下有争议),或者检查应用层的连接关闭逻辑。我曾经就遇到过一个服务因为
TIME_WAIT
过多,导致无法接受新连接的案例,当时就是通过观察这些状态才定位到问题。而如果发现
CLOSE_WAIT
持续不减,那往往意味着本地应用程序没有正确关闭连接,可能存在资源泄漏。通过观察这些关键信息,我们能够更深入地理解系统网络行为,从而有效地进行故障排查和性能优化。