1. 为什么命令总是学了就忘——先搞懂Linux命令的学习方法
在带过好几批实习生和刚转行的运维新人之后,我发现一个特别普遍的现象:大家不是不努力,而是努力的方向不太对。见过不少同学拿着厚厚的命令手册从第一页开始背,背到第三十页就放弃了,因为前面的命令压根没机会用。也见过有人把上百条命令抄在笔记本上,最后真正记住的只有ls、cd和grep。
先说结论:Linux命令不是靠背的,是靠“场景”驱动的。你不需要掌握几千条命令,实际上一个合格的运维或后端开发者日常高频使用的命令可能就五六十条,能熟练用好这五六十条,就已经能覆盖工作中绝大部分需求了。剩下的命令,知道“存在”即可——等真遇到那个场景,你自然会去查,查两次就记住了。
这个标题叫“Linux命令速查宝典”,但我不会把它写成一本按字母排序的命令字典,那是man手册该干的事。我在这里想分享一套我自己这些年实践下来觉得最有效的分类学习法,以及每个类别里那些“高性价比命令”的实战用法。学完这套东西,你会发现自己遇到问题时不再是一脸懵地乱敲命令,而是能快速定位“这属于哪一类问题,该用哪一类命令”。
先给一个小建议:不要试图一次学完所有命令。我建议把命令按“生活场景”分成几个板块——文件操作、进程管理、文本处理、网络排查、权限控制。每一块先用一天到两天时间集中练熟,练的时候也别死记参数,就拿着真实问题去练。比如学文件操作那两天,就真的去整理一个目录结构混乱的文件夹;学进程管理就真的去找一个占用CPU过高的程序并把它处理掉。这样练完基本不会忘。
接下来,我按这个思路把高频命令分类拆解,每一类都会讲清楚“为什么用这个命令”“它的核心参数怎么理解”“有什么坑是新手容易踩的”。这些内容都是平时大家问我最多的问题,我尽量用直白的话讲明白。
2. 文件定位、批处理与权限控制——高频场景里的关键命令实战
2.1 find命令:不仅仅是在目录里找文件
很多新手学find的时候只记住了find / -name "xxx",然后遇到权限报错就不知所措,或者觉得这个命令又慢又不好用。其实find的真正强大之处在于它支持按任何文件属性进行搜索,然后直接对结果执行操作。
我举个例子,你自己试一下就明白了。假设你想找出某个目录下所有超过500MB的日志文件,然后清理掉它们,大多数人第一反应是先du -sh *看看谁大,再手动删。但用find一行就能搞定:
find /var/log -type f -size +500M -name "*.log" -exec rm {} \;这里的关键点有两个。第一,-size +500M表示文件大小大于500MB,注意M是大写;第二,-exec ... {} \;的作用是“对每一个匹配的结果执行后面的命令”,{}是当前文件名的占位符,\;是结束符。很多新手会漏掉这个结尾的分号,结果就是报错。还有一点需要注意:如果文件名里有空格,{}需要加上引号,写成"{}",更稳妥的写法是在-name条件后面直接跟-delete:
find /var/log -type f -size +500M -name "*.log" -delete这个-delete在不涉及复杂处理时比-exec rm更安全,但前提是你已经确认过滤条件足够精确。
再分享一个高频但容易被忽略的技巧:find配合mtime按修改时间找文件。比如要清理三个月前的备份文件,可以这样:
find /backup -type f -name "*.tar.gz" -mtime +90 -exec rm {} \;这里+90表示“超过90天”,如果是-90就是“90天以内”。记住这个正负号的逻辑,很多类似的命令(比如-size、-atime)都是同样的规则。
2.2 文件统计与磁盘占用的正确姿势
du和df是两个名字很像但用途完全不同的命令,我见过不少人混用。简单记:df看的是“整个文件系统还剩多少空间”,比如你的根分区/还剩多少;du看的是“某个目录底下到底占了多大空间”。
排查磁盘满的问题时,我一般分两步走。先用df -h看是哪个分区满了,再用du -h --max-depth=1 /某个目录逐级往下钻,找到是哪个目录最占空间。举个例子:
df -h du -h --max-depth=1 /var | sort -hr | head -20第二行命令的意思是把/var底下第一层子目录的大小列出来,然后按人类可读的大小排序,取前20个。--max-depth=1这个参数特别重要,如果不加,du会递归统计所有子目录,输出结果会非常长,而且会额外消耗不少时间在大目录上。
还有一个性能陷阱值得提醒:du是对整个目录树逐文件统计,如果目录特别大(比如几百GB的对象存储挂载点),执行时间会很长,看起来像卡住了。这时候加个-s参数只汇总当前目录、不进入子目录打印每个明细,速度会快很多。
2.3 权限和用户:从“为什么我不能执行”说起
权限这块最经典的报错就是Permission denied。我遇到过好几次这样的情况:某同学给脚本加了chmod 755,也确认了所有者和组都没问题,但执行的时候还是报权限不足。后来发现原因很简单——脚本第一行是#!/bin/bash,这行没毛病,但他把脚本放在了一个没有执行权限的挂载点上(比如某个noexec的挂载分区),无论文件本身怎么改权限都没用。
排查这类问题,先看三件事:文件权限(ls -l)、所在文件系统的挂载选项(mount | grep 挂载点)、以及 SELinux 或 AppArmor 是否拦截(ausearch或dmesg | tail)。从经验来看,前两个问题是九成情况的根因。
读写权限的实用场景中,需要记住chmod三种表达方式:
- 数字方式:
chmod 754 file,对应rwxr-xr--。7=4+2+1(rwx),5=4+1(r-x),4=r。 - 符号方式:
chmod u+x file,给当前用户加执行权限;chmod -R g+w dir,给同组用户递归加写权限。 - 掩码方式:
umask,决定了新建文件的默认权限。系统里默认 umask 通常是 022,意味着新建普通文件默认是 644。
关于umask多说两句,很多新手不理解为什么刚建的脚本总是没有执行权限、每次都要手动chmod +x。这其实不是系统在为难你,而是默认安全策略故意不给你执行权限。如果你在个人开发环境里嫌麻烦,可以把umask 002写进~/.bashrc,这样新建的文件权限会变成 775,但如果是生产环境,我不建议这样改,保持默认更安全。
2.4 软链接和硬链接:别再傻傻分不清
ln命令看起来简单,但软链接和硬链接的区别经常把人绕晕。我用一句话说明白:软链接是一个“快捷方式”,它存的是目标的路径字符串,目标删了它就成了死链;硬链接是同一个文件数据的另一个名字,相当于多个目录项指向同一个inode,只要还有一个硬链接存在,文件数据就不会被删除。
实操中用的最多的是软链接,比如把某个应用的日志目录链接到独立数据盘:
ln -s /data/app-logs /var/log/myapp这样应用写入/var/log/myapp,实际落盘在/data/app-logs,目录空间大了、迁移也方便。
硬链接有它的限制:不能跨文件系统,链接目录也不行。它最大的用处是做“即时一致性快照”式的备份。比如:
ln /etc/nginx/nginx.conf /backup/nginx.conf.bak这条命令不会复制文件内容,只是给同一个数据加了个名字,瞬间完成,不占额外空间。等下次改了配置、需要回滚时,直接覆盖回去就行。
有个检查技巧:ls -l输出中,硬链接的文件权限位后面那个数字表示链接数。普通文件通常是1,你每创建一个硬链接,这个数字就加1。如果你发现配置文件链接数超过1,说明有别的地方还在引用它,删之前要想清楚。
3. 进程、内存与磁盘排查——定位系统问题的三步套路
3.1 排查CPU飙高:从top到定位进程的完整链路
系统卡了,第一反应是看top,这没错。但top看的是瞬时快照,而且默认按CPU排序,信息比较粗糙。我更推荐按内存占用来排查的顺序和思路。
先说top里最容易被误解的字段。很多新手盯着%CPU看,发现有个进程CPU占用100%,就觉得是它把机器搞卡了。但别忘了看load average,这个值才是系统整体负载的关键。三个数分别代表过去1分钟、5分钟、15分钟的平均负载。如果1分钟值比15分钟值高很多,说明负载正在快速上升;反过来,如果1分钟低而15分钟高,说明高峰已经过去,系统正在恢复。
定位到可疑进程后,下一步是看它的线程和堆栈。top -Hp <pid>可以查看该进程内所有线程的CPU占用,适合处理Java或Python这类多线程应用。想更近一步,用strace -p <pid>跟踪系统调用,或者用gdbattach 上去看栈。这两招在实战中非常有用,比如某应用卡在等待网络IO,strace里会反复出现poll或connect调用。
还有个小工具可能很多人没注意:pidstat。它属于sysstat包,可以按进程打印CPU、内存、IO的统计信息,而且能输出到文件用于事后分析。一条典型的用法:
pidstat -p <pid> 1 10意思是每秒采样一次,共采样10次。这比top的两个刷新间隔之间的数据更适合用来判断CPU占用是持续性的还是瞬时峰值。
3.2 内存排查:free的输出你真的看懂了吗
free -h输出的信息里,used那一列经常让人误判。其实Linux的内存管理哲学是“空闲内存不如拿去缓存”,所以buff/cache占了一大块并不代表内存不够用。真正需要关注的是available这一列,它才是“在不触发大量换页的前提下,还能分配给新进程的内存量”。
如果发现available数值持续走低,甚至si和so(swap in/out)持续有IO,说明内存严重不足,系统正在把内存页换到交换分区。这种情况下最直接的办法就是找到内存大户,看是谁在吃内存:
ps aux --sort=-%mem | head -15这条命令按内存占用排序,一次列出前15个进程。另外,top里按M键也可以切到按内存排序。
排查内存泄漏时,光看进程的RES(常驻内存)是不够的,因为进程可能已经把内存还给glibc分配器但没有归还给操作系统,导致你看RES一直不降。这种情况下可以观察进程的%MEM是否持续稳定增长,或者用valgrind这类工具做更深入的内存分析。从我的实践来看,很多所谓的“内存泄漏”其实是日志框架或者对象缓存机制导致的老年代增长,不一定真是bug。
3.3 磁盘IO排查:响应慢不一定是因为CPU
有时候系统负载不高、CPU也很空闲,但应用就是响应很慢。这时候要查磁盘IO。iostat -x 1命令可以看每块盘的详细指标,重点看%util和await。但有个容易出错的地方:%util100%并不一定代表磁盘“满了”,如果底层是SSD,即使%util100%也可能因为IO合并机制而吞吐量并不低;反过来,某些高并发小IO场景下%util不高但await很高,那才是真正的延迟瓶颈。
定位到是哪个进程在疯狂读写磁盘,可以用iotop。这个工具需要root权限,不默认安装。如果是数据库等应用,通常表现为持续的写日志或刷脏页,这时候要结合应用的配置来判断是正常写入还是异常路径。
还有个更隐蔽的情况:df -h显示磁盘还有很大空间,但应用报“no space left on device”。这通常不是真的空间满了,而是inode耗尽。用df -i一看就能发现,inode用完了。我以前在一个存放大量小文件的采集服务上踩过这个坑,当时清理文件太慢,最后直接把整个分区的文件迁移到新目录重建文件系统才彻底解决。
4. 文本处理和网络排查——数据管道思维与常用排查手法
4.1 grep、awk、sed组合使用的管道思维
文本处理是Linux命令的精华所在,很多人学完单个命令觉得都会了,但一遇到“统计日志里某个接口的平均耗时”这种需求就无从下手。核心问题在于,缺少一种“管道思维”:把文本处理拆成“筛选→加工→统计”三个环节,每个环节用一个命令,用|串起来。
举个例子,日志文件access.log的每一行是这样:
192.168.1.100 [2025/06/01:10:15:23] "GET /api/user/info" 200 0.235 192.168.1.101 [2025/06/01:10:15:25] "GET /api/order/list" 200 1.127需求是统计35秒内/api/user/info这个接口的平均响应时间。两步走:
grep "/api/user/info" access.log | awk '{sum += $NF; count++} END {print sum/count}'grep先把相关行筛出来,然后awk对每一行取最后一个字段($NF在awk里表示“每行的最后一个字段”,这里正好是响应时间),累加并计数,最后在END块里算平均值。
这里有个细节值得注意:awk默认按空格或制表符分割字段,所以每行里的[2025/06/01:10:15:23]这种带空格的]不会影响取最后一列。但如果字段分隔符不是空格,比如是逗号(aa,bb,cc),就需要用-F','指定。比如一个CSV文件,第二列是用户名,要统计出现了多少次:
awk -F',' '{print $2}' users.csv | sort | uniq -c | sort -rn | headsort排序后交给uniq -c统计重复次数,第二次sort -rn按次数倒序排,这套组合拳在处理日志去重、统计Top N时极其常用。
sed的主力场景是“替换”和“按行操作”。比如要把日志文件里的所有ERROR替换成WARN:
sed -i 's/ERROR/WARN/g' app.log注意-i是直接改原文件,这个参数在测试阶段建议别用,先用不带-i的方式把输出打印到屏幕检查确认无误后再加。关于-i的细节:macOS自带的sed和Linux上的GNU sed对-i的语法略有不同,macOS需要写成sed -i '' 's/.../.../g' file,否则会报错。跨平台写脚本时这个差异非常坑,提前踩过的人才知道。
4.2 grep 的几个高频参数:别只会用“grep关键字”
grep最简单的用法确实是grep "关键词" 文件,但要应付真实场景,这几个参数必须掌握:
-r:递归搜索目录下的所有文件。注意如果是二进制文件,输出可能是一堆乱码,加-I可以忽略二进制文件。-i:忽略大小写。排查日志里某关键字时很有用,比如搜 “error” 会漏掉 “ERROR”,别偷懒不加。-v:反向匹配,输出不包含关键词的行。比如查看配置里所有被注释掉的行:grep -v "^#" nginx.conf。-n:显示行号。排查问题时没有行号几乎寸步难行。-o:只输出匹配的部分而不是整行。比如要统计日志里出现的所有IP地址:
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" access.log | sort | uniq -c | sort -rn | head这里-E表示启用扩展正则表达式。需要注意,基础的 grep 默认使用的是基本正则,+、?等符号需要转义或加-E才能生效,这也是新手经常匹配不到内容的原因之一。
4.3 网络排查的日常武器:ping、curl、ss、telnet
网络问题排查的基本盘是ping和curl。ping测的是“主机通不通”,curl测的是“端口通不通、服务有没有响应”。很多人把这两者混为一谈,但实际上ping走的是ICMP协议,很多时候主机能ping通但业务端口连不上,原因可以是防火墙丢包,也可能是服务根本没起来。
我在排查“某个接口连不上”的问题时,四步走:
ping <目标IP>— 基础网络是否可达。curl -v http://目标IP:端口/路径— 看TCP握手和HTTP响应是否正常,-v参数打印完整过程。telnet 目标IP 端口— 只测TCP端口能否建立连接,比curl轻量,适合反向排查“服务在听,但HTTP层有问题”的情况。ss -tlnp | grep <端口>— 看本机这个端口有没有进程在监听。
关于curl的几个容易出错的地方:访问HTTPS站点时,如果目标站点证书有问题,curl默认会拒绝连接。排查内部测试服务时可以用-k跳过证书校验,但生产环境绝对不要这样写。还有-H头参数,调试接口必备,比如:
curl -X POST "http://127.0.0.1:8080/api/login" \ -H "Content-Type: application/json" \ -d '{"username":"test","password":"123456"}'ss命令现在基本取代了老的netstat,输出更清晰更快。一条实用的命令是看当前所有TCP连接状态统计:
ss -tan state established | wc -l这条能快速判断系统当前到底有多少活跃连接,配合ss -s看汇总信息,排查连接数异常增长时非常好用。
4.4 查看日志的利器:tail、less和journalctl
排查线上问题,日志是第一现场。tail -f跟日志简直是运维标配,但有两个坑。第一,如果日志文件被日志轮转重命名(比如从app.log变成app.log.1),tail -f会继续盯旧的“文件句柄”,新写入的内容不会显示。这时候要用tail -F(大写F),它会按文件名追踪、文件轮转后自动重新打开。这个差异在我第一次踩坑时找了半小时才明白。
第二,less查看大日志文件时,按/搜索关键字,按n跳到下一个匹配项,按q退出。但如果文件特别大(几个GB),less打开时也会有一些卡顿。更快的做法是用grep先过滤再输出到临时文件或直接用管道查看,或者至少加--no-init参数减少屏幕初始化开销。
journalctl是systemd时代的日志管理命令,看服务日志特别方便。几个高频用法:
journalctl -u myservice.service -f # 跟某个服务的实时日志 journalctl -u myservice.service --since "1 hour ago" # 看最近一小时的日志 journalctl -u myservice.service -p err # 只看error级别及以上的日志注意-p err表示只看error及以上(包含crit、alert、emerg),日志级别的过滤对排查问题很有帮助。
5. 从速查到工具箱——把自己常用的命令沉淀成速查笔记
5.1 为什么你查完命令就忘:缺少沉淀机制
前面讲了这么多命令和用法,但你如果只是“眼睛看会了”,过两周还是会忘。我自己的做法是:每个项目周期结束后,把这次用到的高频命令整理成一份个人速查笔记,放进一个专门的git仓库里维护。不追求覆盖所有命令,只记录自己真正用过、踩过坑的。这个仓库就是我的“外部大脑”,查一次、沉淀一次、长期积累。
做笔记有一个重要原则:不要只记命令本身,一定要把“当时为什么要用”和“踩了什么坑”写上去。比如只记find /var/log -type f -size +500M -delete,下次看到还是不知道为什么;但如果写“清理日志分区磁盘空间,注意先确认匹配条件,-delete会直接删文件不可恢复”,这段记忆才是可复用的知识。
我常用的格式大概是这样的:
## 磁盘清理 场景:/var分区磁盘满,应用无法写入日志。 排查:df -h确认分区;du --max-depth=1 /var 找大目录。 操作:find /var/log -type f -name "*.log" -size +500M -delete 注意:-delete不可恢复,建议先不加-delete跑一次看匹配到哪些文件。这种笔记积累到一定量之后,会发现很多问题都是同一个套路的变种,查笔记的速度会越来越快。
5.2 给自己做一个“命令速查脚本”
如果你经常需要在多台机器上执行同样的排查流程,可以考虑写一个简单的Shell脚本把这些流程固化下来。我自己有一个sysinfo.sh,一键收集系统状态摘要,日常巡检时直接看输出结果,不用一遍遍敲冗长的命令。
脚本核心内容大概是这样的:
#!/bin/bash echo "===== 系统时间与运行时长 =====" uptime echo "" echo "===== 内存概况 =====" free -h echo "" echo "===== 磁盘空间 =====" df -h | grep -vE "^tmpfs|^devtmpfs" echo "" echo "===== CPU/内存占用前10进程 =====" ps aux --sort=-%cpu | head -11 echo "" echo "===== 当前监听端口 =====" ss -tlnp把这段脚本放到/usr/local/bin/目录下,加执行权限,以后遇到问题先跑一遍,基本上80%的常见故障都能看到线索。
这个脚本最大的价值不是省几秒钟,而是让排查流程标准化。每次先看同一组数据,不容易漏掉一些平时不会注意的指标。
5.3 给新人的几条红线建议
最后聊几条我用“真金白银”换来的教训,希望对刚接触Linux的同学有用。
第一,不要在不确定的情况下使用带-f或-delete的删除类命令。我见过有人为了清理日志写了find / -name "*.log" -delete,结果把一些应用运行依赖的历史日志也删了,虽然不致命但恢复很麻烦。安全做法永远是先用不带删除的形态跑一遍,确认匹配范围,再动真格的。
第二,线上环境修改配置前,养成先备份的习惯。最简单的就是cp file file.bak.$(date +%Y%m%d%H%M%S),一条命令把时间戳带上,回滚时直接找最近的备份。
第三,了解自己的环境。不同的发行版、不同的shell、不同的工具版本,命令行为可能不一样。比如前面说到的sed -i在Linux和macOS的差异、ss和netstat的新旧替代关系。多留意这些细节,能减少很多“照着教程敲却报错”的挫败感。
第四,学会查man手册和--help。没有人能把所有参数记在脑子里,关键不是“记住每个参数”,而是“知道某个命令能解决哪类问题,然后会查它的具体用法”。我在需要精确知道某个参数含义时,最常用的三阶方法是:先man <命令>看完整文档,再命令 --help看速览,最后实在不懂就在测试环境里敲一遍看看行为。
5.4 从速查到形成肌肉记忆
命令的学习曲线不是一个“一直涨”的曲线,而是“前期快速积累、中期大量遗忘、后期通过反复使用形成肌肉记忆”的过程。肌肉记忆是怎么来的?就是在真实场景里反复用,而不是在小本本上反复抄。
我个人的体会是,每个人都会有一批“能用但不熟”的命令,真正熟的永远是最常用的那三五十条。所以与其焦虑“还有多少命令没学完”,不如把已经会的这些练到“手比脑子快”的程度。等到查命令的动作越来越少,你的Linux基本功就已经过了大多数人水平了。
给自己定个小目标吧:接下来的两周,每天刻意练习一条高频命令,把它放进真实场景里用一遍,然后在自己的速查笔记里记一条“踩坑/心得”。两周后你会明显感觉排查问题的速度不一样了。