我刚开始学 Linux 命令时,一直有个很烦的问题:
别人敲 ss -tulnp、lsof -i :8080,像手已经记住了一样。我每次都要搜。
-t、-u、-l、-n、-p 到底怎么记?lsof 后面为什么有时候是 -i,有时候是 -p,还有人写 +D?
后来我才发现,问题不在记忆力。
我一直在背命令,没有理解命令背后的查询逻辑。
先别问参数,先问你想查什么
很多新手学命令时,习惯这样问:
ss 后面应该加什么?lsof 后面应该怎么写?grep、find、ps、netstat 的参数怎么记?
这个问法一开始就偏了。
实际排查时,更该先问这几件事:
比如你敲 ss,你并不是在“使用一个网络命令”。你是在问系统:
当前机器有哪些网络 socket?哪些端口正在监听?8080 是不是已经被占了?这个端口背后是哪个进程?我想看数字端口号,还是服务名?
这样一换,命令就不再是一串暗号。
命令行的本质不是背语法,而是构造查询。
用 Windows 类比一下
如果你用过 Windows 的任务管理器和资源监视器,就很好理解。
你想看程序有没有运行,会打开任务管理器;你想看哪个进程占 CPU,会切到进程列表;你想看端口占用,会去资源监视器的网络面板;你想看系统报错,会打开事件查看器。
Linux 命令也是这个思路,只是它不用图形界面,而是用参数表达筛选条件。
比如:
ss -tulnp
可以拆成几个条件:
-n:用数字显示地址和端口,不把 80 解析成 http
所以它的意思大概是:
把当前机器上监听中的 TCP/UDP socket 列出来,端口用数字显示,顺便告诉我背后是哪个进程。
这就好记多了。
它不是 tulnp 这五个字母的机械组合,而是五个筛选条件。
命令通常是“工具 + 条件 + 对象”
大多数 Linux 命令都可以拆成这个结构:
命令 + 选项 + 参数
比如:
find /var/log -name "*.log"
这句话可以拆成:
-name "*.log":只要文件名符合这个模式的结果
再比如:
grep -i "error" app.log
它的意思是:
你看,参数不是为了让人背得痛苦才存在的。参数是在描述你的问题。
忘参数很正常。真正要练的是:先把问题说清楚。
命令名本身也在提示你
很多命令名是英文缩写,知道来源之后,会好记很多。
ss:socket statistics,查看 socket 统计信息lsof:list open files,列出打开的文件grep:通常理解为 global regular expression print,按模式匹配并打印
比如 lsof。
很多人把它当成“查端口命令”,所以一看到 lsof -i :8080 就觉得奇怪:查端口为什么叫 open files?
因为它本来不是专门查端口的。
它的本意是“列出进程打开的文件”。在 Linux 里,进程访问普通文件、设备、管道、socket,都会通过文件描述符这类接口暴露出来。网络 socket 也会出现在这个体系里,所以 lsof 可以拿来查端口。
这里不要把“一切皆文件”理解得太死。不是所有东西都真的是普通文本文件,也不是随便 cat 一下就能解决。更准确的理解是:Linux 把大量资源用类似文件的接口管理起来,方便进程统一访问。
这层想通了,lsof -i :8080 就不怪了。
ss 查的不是“端口”,而是 socket
我们先把 ss 单独拆一下。
ss 用来查看 socket 信息。socket 可以简单理解成程序进行网络通信时使用的端点。
一个 Web 服务监听 8080 端口,本质上是进程创建了 socket,并把它绑定到本机地址和 8080 端口上。
所以你看到的不是一个孤立的“端口”,而是一组关系:
ss 的参数基本就围绕这些维度来。
常见用法:
ss -lnt
含义是:只看监听中的 TCP socket,端口和地址用数字显示。
sudo ss -tulnp
含义是:查看监听中的 TCP/UDP socket,并尽量显示进程信息。这里经常需要 sudo,因为普通用户可能看不到其他用户进程的完整信息。
ss -ant
含义是:查看所有 TCP socket,包括已建立连接、等待关闭等状态。
如果只想查 8080,可以快速写:
sudo ss -lntp | grep ':8080'
更严谨一点,可以用 ss 自己的过滤表达式:
sudo ss -lntp 'sport = :8080'
这比只靠 grep 更不容易误匹配,比如把 18080 也扫进去。
为什么很多教程还写 netstat
你可能还见过:
netstat -lntp
这个命令不是不能用。问题在于 netstat 属于老的 net-tools 工具集,很多新系统已经不默认安装了。现在更推荐用 ss,它来自 iproute2,速度和信息表达都更适合现代 Linux。
所以写教程时,我建议这样处理:
- 真到现场,先看机器上有什么工具,不要执着于某一条命令
这也是“构造查询”的好处。
你要查的是“哪个进程监听了哪个端口”,工具可以是 ss,也可以是 lsof。目标不变,工具可以换。
新手最容易踩的三个坑
第一个坑:忘记 -n。
不加 -n 时,系统可能会把端口号解析成服务名,比如把 80 显示成 http。有时这挺友好,有时反而影响排查。排障时我更喜欢数字,清楚。
第二个坑:看不到进程就以为没有进程。
ss -tulnp 里 -p 是显示进程信息,但不是所有用户都能看到所有进程。看不到时,先试试:
sudo ss -tulnp
第三个坑:分不清监听和连接。
排查“服务有没有起来”,通常看监听状态。排查“有没有客户端连上来”,要看已建立连接。两个问题不是一回事。
比如:
sudo ss -lntp
更适合看服务是否在监听端口。
ss -ant
更适合看 TCP 连接状态。
你先想清楚要查哪件事,参数自然会少很多。
先把这一篇记住
如果你总是记不住 ss -tulnp,先别怪自己。
你真正要记的不是这五个字母,而是这个问题:
我要看哪些 socket?要不要限制协议?要不要只看监听?端口要不要用数字?要不要显示进程?
能把这个问题问出来,你就已经不是在背命令了。
下篇我们继续拆 lsof:为什么查端口会用“列出打开文件”的工具?lsof -i :8080、lsof -p 1234、lsof +D /var/log 分别在查什么?以及,忘了参数时,怎么用 --help 和 man 现场找答案。