运维知识
悠悠
2025年9月28日

别再傻傻分不清了!ss和netstat到底有啥区别,看完这篇你就懂了

不知道你们有没有发现有些服务器上用netstat命令特别慢,而用ss命令就很快。刚开始的时候我也是一直用netstat查看网络连接状态,直到有一天发现了ss这个命令。说实话,刚开始我也不太理解为什么要换工具,netstat用得好好的啊。但是随着工作中遇到的场景越来越复杂,特别是在一些高并发的生产环境中,我才真正体会到了两者的差异。

今天就来聊聊这两个命令的区别,以及在实际工作中应该怎么选择使用。

netstat的工作原理

netstat这个命令可以说是网络排查的经典工具了,我记得第一次学Linux的时候,老师就教我们用netstat -an来查看端口监听情况。

image-20250928225411654

netstat的工作原理其实就是读取/proc文件系统中的信息。具体来说,它会读取这些文件:

  • /proc/net/tcp:TCP连接信息
  • /proc/net/udp:UDP连接信息
  • /proc/net/unix:Unix socket信息
  • /proc/net/raw:原始socket信息

我之前在一个客户项目中,经常需要查看服务器的连接数,那时候就习惯性地敲netstat -an | grep :80 | wc -l这样的命令。在连接数不多的时候,这个命令执行得还挺快的。

但是问题来了,随着业务量的增长,服务器上的连接数越来越多。有一次活动期间,我照常执行netstat命令查看连接状态,结果等了好几分钟都没出结果。

ss的工作机制

ss命令其实不算特别新了,它在2001年就已经出现了。ss的全称是Socket Statistics,它最大的优势就是直接从内核获取信息,而不是像netstat那样去解析/proc文件系统。

ss使用的是netlink socket与内核通信,这种方式效率更高。netlink是Linux内核提供的一种用户空间与内核空间通信的机制,专门用于获取网络统计信息。

用strace揭秘两者的性能差异

为了更直观地看出两个命令的差异,我用strace来跟踪它们的系统调用。

先看netstat的系统调用:

strace -c netstat -an > /dev/null

image-20250928225522684

输出结果显示netstat主要的系统调用:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0        26           read
  0.00    0.000000           0         4           write
  0.00    0.000000           0        14           close
  0.00    0.000000           0         6           fstat
  0.00    0.000000           0        17           mmap
  0.00    0.000000           0         5           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         1         1 ioctl
  0.00    0.000000           0         2           pread64
  0.00    0.000000           0         2         2 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0        24        10 openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
  0.00    0.000000           0         1           getrandom
  0.00    0.000000           0         1           rseq
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000           0       114        15 total

可以看到netstat执行了大量的read、openat、close操作,这些都是在读取/proc文件系统。

再看ss的系统调用:

strace -c ss -an > /dev/null

image-20250928225617042

输出结果:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0        19           read
  0.00    0.000000           0         8           write
  0.00    0.000000           0        31           close
  0.00    0.000000           0        20           fstat
  0.00    0.000000           0        79           mmap
  0.00    0.000000           0        19           mprotect
  0.00    0.000000           0         2           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2         2 ioctl
  0.00    0.000000           0         2           pread64
  0.00    0.000000           0         2         2 access
  0.00    0.000000           0        12           socket
  0.00    0.000000           0         6           sendto
  0.00    0.000000           0        11           sendmsg
  0.00    0.000000           0        60           recvmsg
  0.00    0.000000           0        12           bind
  0.00    0.000000           0        12           getsockname
  0.00    0.000000           0        36           setsockopt
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         6         4 prctl
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0        19           openat
  0.00    0.000000           0         1           set_robust_list
  0.00    0.000000           0         1           prlimit64
  0.00    0.000000           0         1           getrandom
  0.00    0.000000           0         1           rseq
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000           0       370        10 total

ss的系统调用明显少很多,主要是socket、sendto、recvmsg这些网络相关的调用,这就是netlink通信的特征。

具体使用场景对比

查看监听端口

netstat方式:

netstat -tlnp

ss方式:

ss -tlnp

两者输出格式基本相同,但ss速度更快。

image-20250928225721526

查看特定端口连接

netstat方式:

netstat -an | grep :80

ss方式:

ss -an sport = :80
# 或者
ss -an dport = :80

ss的过滤语法更强大,可以直接在命令中指定条件,不需要管道给grep。

image-20250928225741600

统计连接状态

netstat方式:

netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

ss方式:

ss -s

ss直接提供了统计功能,不需要额外的文本处理。

image-20250928225805256

高级过滤功能

ss的过滤功能确实比netstat强大很多。比如我想查看所有连接到特定IP的连接:

ss -an dst 192.168.1.100

或者查看特定状态的连接:

ss -an state established
ss -an state time-wait

还可以组合多个条件:

ss -an state established dst 192.168.1.0/24

这些功能用netstat实现的话,就得写很复杂的grep和awk命令了。

内存使用对比

除了执行速度,内存使用也是一个重要指标。我用valgrind测试了两个命令的内存使用情况:

netstat在处理大量连接时,内存使用会线性增长,因为它需要将所有/proc文件内容读入内存再处理。

ss的内存使用相对稳定,因为它是流式处理netlink消息,不需要一次性加载所有数据。

在连接数达到10万级别时,netstat可能会消耗几百MB内存,而ss只需要几MB。

实际生产环境的选择

在日常工作中,我现在基本上都用ss了。特别是在写监控脚本的时候:

#!/bin/bash
# 监控TCP连接数
ESTABLISHED=$(ss -an state established | wc -l)
TIME_WAIT=$(ss -an state time-wait | wc -l)

echo "ESTABLISHED: $ESTABLISHED"
echo "TIME_WAIT: $TIME_WAIT"

这种脚本如果用netstat的话,在高并发环境下可能会因为执行时间过长而影响监控的实时性。

但是有些时候,我还是会用netstat。比如在一些比较老的系统上,可能ss的版本比较老,功能不够完善。还有就是查看路由表信息,ss是没有这个功能的:

netstat -rn  # 查看路由表

输出格式差异

两个命令的输出格式略有不同。netstat的输出比较传统:

Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN

ss的输出信息更丰富:

State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
LISTEN     0      128          *:22                       *:*
LISTEN     0      100    127.0.0.1:25                       *:*

ss还会显示一些额外的信息,比如拥塞窗口大小、重传次数等,这些对网络调优很有用。

兼容性考虑

从兼容性角度来说,netstat几乎在所有的Linux发行版中都有。ss虽然也很普及,但在一些比较老的系统中可能版本较旧。

我之前遇到过一个情况,在CentOS 6的系统上,ss命令的过滤功能就比较有限,很多高级特性都不支持。这时候还是得回到netstat。

不过现在大部分的生产环境都是比较新的系统,ss的兼容性问题基本不用担心。

脚本中的最佳实践

在写自动化脚本时,我建议优先使用ss,并且要考虑兼容性:

#!/bin/bash
# 检查命令是否存在
if command -v ss >/dev/null 2>&1; then
    CONN_COUNT=$(ss -an state established | wc -l)
elif command -v netstat >/dev/null 2>&1; then
    CONN_COUNT=$(netstat -an | grep ESTABLISHED | wc -l)
else
    echo "Neither ss nor netstat found"
    exit 1
fi

echo "Established connections: $CONN_COUNT"

这样既能利用ss的性能优势,又能保证在老系统上的兼容性。

写在最后

从netstat到ss的转变,其实也反映了Linux系统工具的发展趋势。新的工具往往在性能和功能上都有所改进,但老工具也有它存在的价值和适用场景。

通过strace的分析,我们可以清楚地看到两个命令在实现机制上的根本差异。netstat通过文件系统接口获取信息,而ss直接与内核通信,这就决定了它们在性能上的差异。

作为运维人员,我们需要与时俱进,学习新的工具和技术,但也不能完全抛弃传统的工具。关键是要理解每个工具的特点和适用场景,然后在实际工作中做出合适的选择。

在高并发、大连接数的环境中,ss明显是更好的选择。但在一些特殊场景下,netstat仍然有它的用武之地。掌握了两个命令的特点,在不同场景下灵活选择,才能更高效地完成工作。


如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!

公众号:运维躬行录

个人博客:躬行笔记

文章目录

博主介绍

热爱技术的云计算运维工程师,Python全栈工程师,分享开发经验与生活感悟。
欢迎关注我的微信公众号@运维躬行录,领取海量学习资料

微信二维码