1. 文件与目录操作:高频场景下最容易被坑的几条命令
说实话,Linux 常用命令 这类标题在网上能搜出一大堆,大部分都是把 man 手册抄一遍再排个版。但我今天想聊的,是那些你天天都在用,却很可能在某个细节上栽过跟头的命令,以及我这些年遇到真实事故后总结出的用法。
先从一个面试高频场景说起。很多人背过 ls -l、rm -rf、find / -name 这三件套就觉得自己会了,但真到了生产环境,往往连第一步都踩不稳。比如 ls -lh 这个参数组合,新手最喜欢加 h 让文件大小显示成 K/M/G,确实直观。可你有没有注意过,文件超过 100M 之后终端里显示的 100M 其实是四舍五入的结果,真正要精确看还得靠 ls --block-size=1 或者 stat 命令。我在一次排查磁盘占用时就吃过这个亏,脚本里用 ls -l 解析第五列拿到的大小和 du 统计的完全不匹配,后来才醒悟 ls 显示的是文件逻辑大小,du 统计的是实际占用块的大小,对稀疏文件来说这两个数值能差出几个数量级。
第二个大坑是 rm。我知道很多教程都会教你 "rm -rf 慎用",但很少有人讲清楚替代方案。我的一个习惯性做法是:进入一个陌生目录,想清理东西时,第一反应不是 rm,而是先 du -sh * | sort -h 看看谁占了空间,再根据实际情况谨慎操作。真要删,也建议先 mv /path/to/ target /tmp/trash-$(date +%Y%m%d),把文件挪到临时区而不是直接抹掉。这个习惯救过我两次,一次是误把备份目录当成了临时目录,另一次是脚本里的变量没拼全面导致路径变成了根目录。所以你问我 Linux 系统管理最重要的一条命令是什么,我的答案不在命令本身,而在风险控制意识。
还有一个被低估的命令是 find。大多数人都用过 find / -name "xxx" 这种全盘搜索,这个用法在大目录下会卡到你怀疑人生,而且很容易因为权限问题刷屏。实际工作中我推荐这样组合:
bash复制find /var/log -type f -name "*.log" -mtime +30 -exec ls -lh {} \;
注意 -mtime +30 表示修改时间超过 30 天的文件,-exec 后面必须加分号结尾。很多人在这里漏掉转义分号导致语法错误,这是个经典问题。find 的另一个高阶玩法是 -prune,用来排除指定目录:
bash复制find / -path /proc -prune -o -path /sys -prune -o -type f -name "*.conf" -print
这条命令在排查配置时非常实用,可以避免反复被虚拟文件系统的海量节点干扰。对于刚入门的读者,我的建议是先别急着背命令,把 pwd、cd -、ls -la 这几个基础操作练到反射级别,再逐步加入 find 的条件参数,比一次性啃完整个命令手册有效得多。
另外补一个我最近才纠正的错误认知:文件名的通配符展开。很多教程说 *.log 会匹配所有 log 结尾的文件,但如果你当前目录下没有任何匹配项,shell 会把这个通配符原样传给命令而不是报错。这意味着 rm *.log 在没有匹配文件时,实际上是在尝试删除一个名叫 *.log 的字面文件。真实场景里当然很少见到这种文件,但一旦脚本里出现了这种逻辑缺陷,排查起来会非常痛苦。我现在写脚本时只要涉及通配符,一定会先 ls 一下确认匹配数量,再继续后续操作。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. grep、sed、awk 三件套:从只会查日志到能写一行流式处理
如果说文件操作是 Linux 常用命令 的入门门槛,那么 grep、sed、awk 就是区分"会敲命令"和"会写命令"的分水岭。这三条命令单独看都不难,但组合起来能解决的问题,远比很多人想象中多。
先说 grep。大多数人对它的认知停留在 grep -i "error" 这种忽略大小写的搜索。但在实际运维和开发场景里,我最常用的是这两个参数:-E 启用扩展正则,-A 和 -B 输出上下文。比如线上服务突然报警,需要快速定位异常附近的内容,一条命令就能搞定:
bash复制grep -E -A 5 -B 2 "Exception|ERROR" app.log
这里 -A 5 表示错误行之后打印 5 行,-B 2 表示之前打印 2 行,方便直接看到异常发生前后的业务上下文。排查日志时,这种用法比先把文件拉下来再用编辑器搜索要快得多。顺便提一句 grep -l 和 grep -L 的区别:-l 列出包含关键词的文件名,-L 列出不包含关键词的文件名,这两个在批量检查多个配置文件时特别有用,可以配合 find 把结果交给它。
然后是 sed。我知道很多人觉得 sed 语法晦涩,正则加反斜杠看得头晕。但如果只学三个用法,性价比极高。第一个是 sed -n '5,10p' file,打印指定行区间;第二个是 sed -i 's/old/new/g' file,原地替换内容(注意 macOS 版本需要 sed -i '',Linux 版本不需要加参数,这个跨平台差异踩中过不少人);第三个是 sed -n 's/pattern//p',只输出匹配并做替换的行。这三个用法覆盖了大部分日常需求,剩下的边角场景再查文档也不迟。
这里必须强调一点:sed -i 在生产环境慎用。理由很简单,原地替换会直接修改源文件,一旦正则写错,数据就丢了。我的做法是先把 -i 换成不带参数的预览模式,跑一遍看下替换结果是否正常,确认无误后再加上 -i。如果文件系统支持,还可以用 sed -i.bak 让它自动生成备份文件,多一层保险。
接着是 awk。这个命令看起来是"按列处理文本",但实际威力体现在它内建的变量和函数上。举个例子,压力测试后要统计接口的平均响应时间,日志格式是这样的:
code复制2024-06-01 10:00:01 [INFO] POST /api/order latency=132ms
2024-06-01 10:00:03 [WARN] POST /api/order latency=521ms
用 awk 提取 latency 列并求平均:
bash复制awk '/POST \/api\/order/ {match($0, /latency=[0-9]+/); latency=substr($0, RSTART+8, RLENGTH-8); sum+=latency; count++} END {print sum/count}'
这段稍微有点绕,核心在于 match 和 substr 的组合,从一行文本里提取数字部分。Linux 系统高手和新手之间一个显著的差异就在这里:新手习惯先 grep 过滤,用肉眼读数据;老手则整条管道下来,数据直接算好放在眼前。
awk 里最容易被忽略的是 BEGIN 和 END 块。BEGIN 在读取每一行之前执行,适合定义分隔符 FS="," 或初始化变量;END 在文件处理完后执行,适合输出统计结果。举一个顺手就能用的例子,统计访问日志里每个 IP 出现次数并排序:
bash复制awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
这条管道命令在很多面试里被当成考题,但更重要的是你能读懂它每一步在做什么:取第一列、排序、去重并计数、按数字逆序排列、取前 20 行。这套思路用到日常运维中,能够非常高效地定位热点源 IP。
最后一个提醒:grep、sed、awk 之间不是互斥的,组合使用才能发挥最大价值。管道符号 | 在这个体系里就是积木对接的桥梁,前一个命令的输出变成后一个命令的输入,组合出多种流式处理方案。我在排查批量文本替换、日志统计、配置校验等场景时,几乎都是三者在一条命令链里各司其职。
3. 进程、内存与磁盘排查:系统嚷嚷不舒服时该怎么问诊
系统变慢了、服务挂了、磁盘满了,这是所有用 Linux 服务器的人迟早会遇到的事。我见过不少人一慌就重启大法,把服务和系统都 reboot 一遍,虽然很多时候确实能恢复,但你永远不知道根因是什么,下次还会踩同一个坑。这一章我讲讲遇到系统瓶颈时,我实际的排查步骤是什么。
首先是 top。注意看两块:负载均值(load average)和每个进程的 %CPU、%MEM。load average 后面三个数字分别代表 1 分钟、5 分钟、15 分钟的平均负载。如果 15 分钟数值远大于 1 分钟数值,说明系统负载在过去一段时间持续上升,不是瞬时抖动;反之则可能是短时高峰。单看数字不够,还要结合 CPU 的核心数——负载大于核心数,说明任务排队严重,CPU 成为瓶颈。这个判断比单纯看 %CPU 更准确,因为多核系统上某个进程占 100% 只代表它用满了一个核,整体负载可能并不高。
top 进入界面后有几个快捷键值得记一下:P 按 CPU 排序,M 按内存排序,1 展开每个 CPU 核心的占用情况,c 显示完整命令行路径。很多时候一个进程名字叫 java,但你想知道它到底带了什么参数,按 c 就全看到了。我之前排查过一个 CPU 飙高的问题,top 里只显示 nginx,按 c 才发现是某个业务路径把 nginx -s reload 循环执行了,导致 CPU 被系统信号处理占满——这种细节不展开看是很难定位的。
然后是 free 命令。很多人以为 free 看的是"还剩多少内存",其实 free 输出里的 available 才更接近"还能分配多少"的概念。因为 Linux 内核会尽量把空闲内存用作缓存(cache),而缓存可以随时释放给新进程。如果只看 free 列,你会误以为内存快满了,实际上系统还能游刃有余。我处理过一个内存告警,运维同事说 free 显示只剩 300M,但我一查 available 还有 8G,后来确认是磁盘频繁读写导致缓存占用虚高,加上监控告警阈值设置不当,虚惊一场。所以在看内存指标时,优先关注 available 和 used(减去 cache 和 buffer 后)这两个数。
接着是 ps。ps aux 每个字段都有意义,但我建议优先关注 STAT 列。R 表示运行中,S 表示可中断睡眠,D 表示不可中断睡眠(通常是等待 I/O),Z 表示僵尸进程。D 状态如果大量出现,说明磁盘或内存子系统有问题;Z 出现一两个可能只是正常的短暂状态,但持续存在就说明父进程没有正确处理子进程退出信号。处理僵尸进程的办法一般不是直接杀 PID(已经死了杀不掉),而是找到父进程,检查它是否正确调用了 wait()。如果父进程是 init/systemd 也没法清理,那就只能重启节点了。
再来看磁盘。df -h 看文件系统使用率,du -sh 看目录占用。但这里有一个隐藏很深的坑:df 显示空间不足,可 du 加总却远小于它。这种情况多半是有文件被进程占用后删掉了,但句柄没释放,空间实际还被扣着。排查方法是用 lsof | grep deleted 找到那个进程,重启它之后空间就释放了。我遇到过 df -h / 显示 100% 导致数据库无法写入,跑 du -sh / 却只有 60G 的诡异场景,最后就是用这种方法定位到一个日志文件被 rsyslog 持续写入、同时又被 logrotate 删掉但没重启服务的情况。
进程、内存、磁盘三者相互关联。我通常的排查顺序是:先 top 看负载和 CPU 状态,再 free 确认内存是否够分,然后用 df 和 du 检查磁盘空间,最后用 ps 和 lsof 判断是否有异常进程或未释放句柄。这套流程已经帮我处理过不下十次线上事故,大部分情况下不需要上什么监控平台,几个命令就能定位根因。
另外,kill 命令的语义值得认真对待。默认的 kill PID 发送的是 SIGTERM,通知进程"请自己收尾退出",这是优雅停止;kill -9 PID 发送的是 SIGKILL,内核直接终止进程,没有协商余地。很多人图省事一律 kill -9,但这是有代价的:进程内的状态可能不一致,数据缓冲区来不及落盘,其他依赖它的服务也会瞬间报错。我的习惯是先用默认 kill 等几秒,超时或确认卡死后才考虑 -9。这个顺序在生产环境里极其重要,尤其是数据库或有状态的中间件。
4. 网络与日志排查:连接层出问题时的黄金链路
服务进程跑得好好的,文件系统也正常,但用户就是反馈访问不了,这时候就得进入网络排查环节。Linux 命令里这部分的工具非常多,我不打算面面俱到,而是分享一套我实际解决问题的排查链路。
第一步是确认端口监听状态。生产环境经常会遇到"服务起来了但外面访问不了"的迷案,这时候先跑:
bash复制ss -lntp
-l 只看监听端口,-n 用数字显示 IP 和端口(不做 DNS 反解),-t 看 TCP,-p 显示占用进程。只要看到 0.0.0.0:8080 或 :::8080 这种监听地址,说明进程已经在特定端口上等待连接;如果只看到 127.0.0.1:8080,说明它只监听了回环地址,局域网和外网当然访问不了。这个原因在很多开发同学的本地环境里出现过,服务配置没改成 0.0.0.0,自己本机测试没问题,一脱离本机就歇菜。
现在的 ss 是替代老命令 netstat 的新一代工具,输出更快且信息更多,netstat 在很多新版发行版里已经不再默认安装了。我建议直接学 ss,没必要在 netstat 上花时间了。
第二步是看端口连通性。目标机器确认监听在外网地址之后,下一步用 telnet、nc 或 curl 主动探测。现代安装环境不一定有 telnet,这时候 nc 更灵活:
bash复制nc -vz 192.168.1.100 8080
-v 输出详细信息,-z 只扫描端口不发送数据。如果超时或者拒绝连接,就说明路径上有问题,可能是防火墙、安全组策略,也可能是中间交换机过滤器。这一步能快速划定问题边界:目标端口本身通不通,不通的话究竟是主机层面还是网络路由层面。
第三步是查看网络路径。ping 测的是 ICMP 通不通,traceroute 则能展示经过的每一跳。但要注意,很多云环境禁止 ICMP,ping 不通不代表上层服务不可达,所以别被表面现象误导。我遇到过 AWS 和国内云的安全组默认禁 ICMP,用户反映"网络断了",我用 ping 确实全丢包,但 ss 和 curl 实际访问服务完全正常。从那以后,判断网络我优先用 curl 测实际业务端口,而不是 ping。
curl 其实是一名被低估的网络排查选手。它不仅能测通不通,还能看响应状态码、耗时和协议细节:
bash复制curl -o /dev/null -s -w "HTTP状态码:%{http_code} 连接耗时:%{time_connect}s 总耗时:%{time_total}s\n" http://127.0.0.1:8080/health
输出的每项指标都能直接帮助你判断瓶颈所在:time_connect 长说明 TCP 握手慢,time_total 长但 time_connect 短说明是服务端处理慢。这个命令在处理"用户感觉慢"类问题时,比一遍遍看浏览器转圈高效得多。
如果需要更细粒度地排查请求是否发出、响应是否回来,可以上 tcpdump 抓包。这个命令对新手不太友好,但掌握基本用法并不难:
bash复制tcpdump -i eth0 -nn port 8080 -c 10
-i 指定网卡,-nn 不做域名和端口反解,port 8080 按端口过滤,-c 10 抓到 10 个包就自动停止。在抓包结果里你会看到 SYN、SYN-ACK、ACK 这类三次握手的字段。如果只看到发送 SYN 但一直没有 SYN-ACK 返回,说明包可能被防火墙拦了;如果三次握手完成但业务请求一直无响应,问题就在应用层。
日志这块,除了上一章提到的 grep 日志文件,还有一个高频命令 tail -f。实时跟踪日志输出时很好用,但生产环境多文件同时跟踪场景下,我这几年更常用的是 journalctl(如果你的服务由 systemd 托管):
bash复制journalctl -u my-service -f --since "2024-06-01 10:00:00"
-u 指定服务单元名,-f 实时刷新,--since 限定时间范围。这套命令能直接查询服务进程的 stdout/stderr,比手动寻找日志文件路径方便很多。遇到 crash 后重启的服务,journalctl -u xxx -b -1 还能查看上一次启动的日志,这对定位启动崩溃问题尤其有用。
日志排查还有一个思路值得推荐:不要只搜 error 关键字。很多时候业务逻辑没有报 error,但状态码或特定指标已经偏离正常。比如 5xx 比例突然升高,可以先搜 "HTTP/1.1\" 5 或 status=5 这种带状态码的模式;如果数据没写对,则搜特定的错误码或业务异常标志。结合上一章的 awk,可以快速按错误类型统计,有数据支撑再下结论,而不是靠感觉。
5. 面试题背后真正想考的能力:常用命令的系统化理解
这个话题得从招人和被招的双重视角来聊。linux 面试题 和 linux 常用命令面试题 的热度一直不低,很多候选人背了 ps、top、grep 一堆命令但依然过不了面,原因在于面试官考察的从来不是"你知道这条命令",而是"你在真实场景下会不会用"。我参与过不少技术面试,面试官通常用这几种方式提问:
第一种是场景题:"服务器 CPU 飙高,你怎么排查?"这种题没有标准答案,但更好的回答里通常会出现一条清晰的链路:先 top -Hp 定位高占用的线程,再用 printf '%x' 把线程 ID 转成十六进制,接着 jstack 或 pstack 导出线程栈(如果是 Java 应用),最后结合代码定位到具体行。这个链路的核心不是哪一条命令,而是你对"从整体到细节"的排查方法论是否有体感。
第二种是概念题:"grep 和 egrep 的区别?"很多旧教程还在强调 egrep 是扩展正则,但现代 GNU grep 直接用 grep -E 就能开启扩展正则,egrep 本身已经是一个兼容别名了。如果你只背结论不理解为什么会有这个区别,一旦换到 BusyBox 或 BSD grep 环境,可能又会迷茫。理解命令产生的历史背景,比死记参数重要得多。
第三种是原理题:"为什么文件删了但磁盘空间没释放?"这就是我在磁盘章节提到的场景:进程持有已删除文件的句柄。理解背后的机制,其实靠的是对 inode 和文件描述符的认知,而不是命令本身。lsof | grep deleted 只是工具,重要的是知道文件在 Unix/Linux 里是"目录项 + inode + 数据块"的组合,删除文件只是把目录项标记为删除,数据块要等所有打开它的进程关闭后才真正释放。面试官听到你能把这个过程说出来,自然会认可你的深度。
所以一条学命令的建议:别按"命令清单"去背,而是按"问题场景"去归类。把命令安插到你熟悉的故障排查流程中,比如端口不通时用什么、磁盘满时用什么、日志太大时用什么,当你形成这种条件反射时,面试题和真实运维都难不倒你。
这套思路同样适用于非专业读者。如果你刚接触 Linux,不需要一次学完所有命令。先从文件查看和目录切换开始,然后是文本处理和日志过滤,再进入进程和网络排查层面,最后用 shell 脚本把多条命令串起来。整个学习路径像一个金字塔,底层是单条命令的熟练度,中间层是组合管道的思路,顶层是排查方法论和自动化能力。我在带新人时一直强调:命令背得再多,不会分析问题等于零;反而你对分析过程越有感觉,新命令学起来也越快。
我个人建议创建一个"命令笔记本",把每次踩坑后学到的组合用法记录进去,比如"删除占用空间但没释放的文件排查"、"按 IP 统计访问量"、"检查证书过期时间"这类实用片段。过一两个月回看,你会发现自己已经能熟练运用几十个命令组合了。这比任何命令行速查表都管用,因为每条命令都带着你具体的业务理解和踩坑记忆。
最后分享一个日常习惯:每周花十分钟,在一台测试机上故意搞点乱子,比如开一堆僵尸进程、填满某个小分区、把服务绑到回环地址,然后用前面提到的命令链条把问题找出来。模拟故障的练习越多,真遇到事故时你越冷静。Linux 命令行世界的核心不是"会输入命令",而是"知道去哪找线索、用什么工具交叉验证"——这才是从会用走向精通的分水岭。
