
1. 先放下命令表理解Linux命令的设计哲学很多人接触Linux命令第一反应就是“背”。找一本命令大全从ls、cd开始一路背到tar、rsync背了忘、忘了背最后遇到实际问题还是只会ls和cd。我在带新人的时候经常说一句话Linux命令不是靠背学会的是靠“理解它的设计思路”学会的。一旦你理解了Linux命令背后那套统一的逻辑几百条命令就不再是零散的知识点而是同一个思维模型下的不同变体。Linux命令的核心思维我总结下来就三条一切皆文件、组合优于单体、文本流是通用接口。听起来有点抽象但拆开看其实特别简单。先说“一切皆文件”。在Linux世界里普通文件是文件目录是文件磁盘是文件网卡是文件甚至进程的运行状态也是文件。你用cat读一个普通文本能cat但你知道吗cat /proc/meminfo能看到内存信息cat /sys/class/net/eth0/address能读到网卡MAC地址。这就是这个设计哲学的实际体现当你把设备、状态、配置都抽象成文件就能用同一套命令cat、grep、echo、重定向去操作它们。所以学Linux命令本质上不是学每条命令的“说明书”而是学一套通用的“文件操作逻辑”。再说“组合优于单体”。Windows用户习惯了GUI每个操作是一个按钮Linux的哲学则是每个命令只做一件小事然后把小事连接起来完成复杂任务。ls只负责列出目录grep只负责过滤文本sort只负责排序但把它们用管道串起来就能完成一条很复杂的分析流程。这个思路和搭积木一样你的核心能力不是记住更多积木形状而是知道怎么把它们拼起来。后面我会专门演示几条组合命令那是全文的精华。最后是“文本流”。Linux命令之间靠什么通信不是结构化的数据包不是API调用而是最朴素的文本流。一个命令的“标准输出”可以当作另一个命令的“标准输入”管道符号|就是这个传导纽带。因为一切都是文本所以你可以随时插入一个grep来过滤插入一个tee来留存过程数据插入一个wc -l来计数。这个设计让命令之间的组合几乎没有任何“接口适配”成本也是Linux能做得到“无数小命令无限组合”的基础。所以学习路线应该是先理解这三条哲学再学高频命令最后练组合思维。带着这个认知框架去学你会发现再也不需要死记硬背了。1.1 一切皆文件与文本流思维“一切皆文件”这句话新手听了一头雾水老手却觉得这是Linux最优雅的设计之一。我举个实际场景你在排查一台服务器为什么卡顿第一个反应是看CPU和内存。如果不懂“一切皆文件”你可能会去找某某监控工具但懂了这个哲学你会很自然地执行cat /proc/loadavg cat /proc/meminfo | head -20/proc目录就是内核映射到文件系统里的“状态窗口”它不是一个真实磁盘目录而是一个虚拟文件系统。你用cat去“读文件”实际上是在读取内核的实时数据。刚接触Linux的人第一次发现/proc的时候往往会有一个“原来如此”的感觉——整个操作系统的运行状态全是用文件形式摆在你这儿了问题是你知不知道去哪里看、怎么看。这个哲学还体现在设备操作上。比如你想往一个US盘写数据在Linux下这个U盘会被映射成一个设备文件通常叫/dev/sdb1你往这个文件里写数据就等于往U盘里写数据。但这里我必须加一句警告直接操作设备文件非常危险新手千万不要乱写我就是吃过亏的。有一次我手误把一个分区路径搞错了写错了设备文件差点把另一块数据盘给抹掉。所以说“一切皆文件”是一把双刃剑理解它的同时也要对底层操作保持敬畏。再谈文本流。文本流思维最好的学习入口就是管道符|。它左边是命令的标准输出右边是下一个命令的标准输入。我见过不少新人代码写得不错但一用管道就懵根本原因是他们不知道每个命令默认输出的是什么、从哪里读输入。这里有个特别重要的细节绝大多数命令把处理结果写到“标准输出”stdout把错误信息写到“标准错误”stderr。这两个流默认都打到屏幕上看起来没区别但当你把它们重定向到文件或者用管道传给下一个命令时区别就出来了。比如grep error app.log output.txt 21这个命令的意思是把grep的结果输出到文件output.txt同时把错误输出(2)也重定向到标准输出(1)再进同一个文件。要是不加21你只会看到正常结果进了文件报错的信息却仍然刷在屏幕上这在写脚本排查问题时特别容易踩。1.2 组合优于单体管道、重定向、通配符三大件通配符、重定向和管道是Linux命令的“三大件”它们决定了你是只会敲单个命令还是能把命令串成工作流。通配符是用来匹配文件名的最常见的三个是*匹配任意多个字符、?匹配单个字符、[]匹配括号内的任意单个字符。比如你有一个目录里既有access_2023.log、access_2024.log也有error_2024.log想只对“2024年所有日志”做操作可以写ls *_2024.log这里的*匹配了前面的“access”或“error”部分。看起来简单但通配符和循环结合会非常有威力。我曾经用一条带通配符的循环命令批量压缩了几百个日志文件for f in *_2024.log; do gzip $f; done注意这里我加了双引号包住$f这是一个极其重要的习惯。如果文件名里有空格不加引号命令就会炸。很多新人写循环不引号遇到带空格的文件名命令直接断成两截排查半天发现是引号问题。重定向就是和前者覆盖写入后者追加写入。这俩的区别我遇到太多人搞混了。会把目标文件清空再写入你要是想把日志追加到旧文件后面用了前面的历史数据就全没了。我的建议是凡是想保留原内容的场景一律默认用只有明确想清空重建时才用。另外还有个特别容易忽略的点重定向目标文件会先被创建/截断再执行命令。如果你执行cat a.txt a.txt这种自己覆盖自己的命令文件会被先清空然后读到的内容就是空的。这种坑不是没人踩过。管道前面说过了但我要补充一个排障级别的细节管道默认只传递标准输出标准错误不进去。所以grep error app.log | wc -l如果报错信息出现在屏幕上你是看不到的因为报错走的是标准错误。这就是为什么很多脚本要统一加上21的原因——把错误也拉进管道或文件里才不会漏掉关键报错。说了这么多其实组合思维最后就是一句话把一个复杂任务拆成多个简单命令再用通配符匹配对象、用重定向控制数据去向、用管道串联处理逻辑。这是Linux命令使用水平的分水岭。1.3 不要背参数man、--help、history三条路有人说Linux命令太难参数几十个根本记不住。我的回答是参数本来就不是用来记的是用来查的。每个命令都有自带文档关键是你得会查。最基础的是man全称manual手册。执行man ls会进入一个分页浏览界面里面详细描述ls的每个参数。很多新手第一次进man不知道怎么退出卡在里面按半天没反应其实退出很简单按q就行。而且man翻页跟less是一样的空格翻下一页、b翻上一页、/关键字在当前页搜索。掌握这几个按键你就能在man里自由穿梭这比背参数表高效十倍。--help是一个更“轻”的文档入口。大多数命令支持命令 --help它会直接在终端输出一段精简的参数说明不用进分页界面。适合你想快速回忆某个命令的某个参数时用。我个人的习惯是不确定参数了先--help快速扫一眼想系统了解某个命令的全部能力才去看man。history则是你自己的命令历史。执行history能看到过去敲过的所有命令配合CtrlR可以反向搜索历史输入几个关键字就能把以前执行过的命令捞回来。我工作中大概有三分之一的长命令是靠历史记录捞回来的根本不用重新打字。三条路径结合基本可以覆盖大部分“记不住”的问题。真正的技巧不是记参数而是把手边最常用的30条命令的参数用熟剩下的“用到再查”。2. 高频实战命令的三类核心场景有了上面的思维框架接下来进入实操层。Linux命令那么多但真正每天高频使用的其实集中在三类场景找东西、看状态、处理文本。我把这三类一一拆开讲每一类里都会穿插选型逻辑和避坑建议。2.1 找文件与定位问题find、grep、locate怎么选“找东西”是Linux最高频操作之一。但同样是找不同的场景工具完全不同很多人一开始就把find和grep混在一起这是个误区。find是“按文件属性找文件”。比如你想找/var/log下最近7天修改过的日志文件find /var/log -type f -mtime -7这里-type f限定只要普通文件-mtime -7表示修改时间在7天以内。find的强大之处在于它不仅是查找还可以对找到的结果直接执行命令这个后面组合实战会讲到。新手用find最常犯的错是不加路径限制直接find / -name *.log结果就是遍历整个文件系统卡到你怀疑人生还可能因为权限问题刷出一大堆错误。正确姿势是先缩小范围或者加上2/dev/null屏蔽权限报错。grep是“按文件内容找线索”。它的核心能力是搜索文件里的文本模式。你怀疑某个配置文件里设置了某个参数但不知道在哪几个文件里直接grep -r max_connections /etc/-r代表递归搜索目录。还有两个必记参数-i忽略大小写-n显示行号。我排查问题时的习惯是先在搜索范围比较大的地方用grep -rn找到线索文件后再配合sed -n或者awk去精确提取内容。grep还有个变体叫egrep等价于grep -E支持扩展正则表达式比如同时匹配多个关键字grep -E error|fatal|exception app.log这个用法在做日志汇总时特别爽。locate是一个基于数据库的快速查找工具。它本质上是提前给文件系统建了个索引查找速度远快于find代价是索引不是实时的刚创建的文件可能要等更新后才能被找到。所以locate适合找“不常变的系统文件”比如某个库文件路径忘了find适合找“最近产生的业务文件”。两者并不冲突按需选择。一句话总结这三者find找文件、grep找内容、locate走捷径。方向对了效率自然上来。2.2 看状态与查进程ps、top、lsof、ss怎么用排查服务器问题第一步永远是“看状态”。这一块我按使用频率排序讲。top是系统资源动态监控器。进入top界面后默认按CPU占用率排序所有进程按P键按CPU排序、按M键按内存排序按q退出。这些交互按键第一次用的人往往不知道我建议记熟P、M、q三个就够入门了。如果你觉得top的输出过于杂乱可以只看我们关心的几个指标load average三个数字分别对应1分钟、5分钟、15分钟的平均负载、CPU的us用户态、sy内核态、waI/O等待以及内存的available。我排障时的习惯是先看load average和wa如果wa偏高基本可以判断是磁盘I/O吃紧下一步就会去用iostat或iotop定位具体进程。ps是进程快照查询器。top看的是实时情况但你想查“某个进程现在还在不在、PID是多少”ps更直接。最常用的组合是ps -ef | grep java这个命令把全量进程列出来然后通过grep过滤出Java进程。但这里有个经典坑grep java会把grep本身也匹配进去因为命令行里包含“java”字符串。所以你会看到一条grep自己的进程。解决方法是加一个排除ps -ef | grep java | grep -v grep或者用更明确的模式匹配。另外想看某个PID对应的完整启动命令用ps -fp 12345它会把PID为12345的进程的完整命令行、父进程、CPU、内存时间一起列出来。我在排查启动参数问题时经常用这个命令比翻配置文件快得多。ss是网络连接查看器替代老牌的netstat。看端口占用ss -lntp-l表示只显示监听中的连接-n用数字显示端口不解析服务名-t只看TCP-p显示对应的进程名和PID。这四个参数组合是我排查“端口被占用”问题的首选。你需要记住一个判断逻辑如果ss -lntp输出里没有你要的端口说明程序根本没起或者起在了别的端口上别再纠结“占不占用”先去查进程为什么没监听成功。lsof是一个“万能胶”工具它能列出进程打开的所有文件。因为Linux一切皆文件所以lsof能查的东西特别多某个文件被哪个进程占用、某个端口被哪个进程监听、某个进程打开了哪些文件。最常用的两种lsof -i :8080 # 谁占用了8080端口 lsof -p 12345 # PID 12345打开了哪些文件比如你删除了一个日志文件但磁盘空间没有释放十有八九是某个进程还在“持有”这个已被删除的文件。执行lsof | grep deleted就能找到那个罪魁祸首进程。2.3 文本处理三板斧awk、sed、sort/uniq的基本姿势Linux排障场景里最绕不开的就是处理日志。日志本质是一堆重复格式的文本而文本处理的核心工具就是awk、sed、sort、uniq这四个。awk像一个“列提取器 条件过滤器”。它的默认行为是按空格连续空白拆分每一行然后用$1、$2引用第1列、第2列。比如访问日志里每行格式是IP地址 时间 请求路径 状态码你想提取所有状态码为500的行中的IP可以写awk $4 500 {print $1} access.log注意awk里条件写在前面动作写在{}里。如果列分隔符不是空格而是逗号之类用-F指定awk -F, {print $2} data.csvawk还有很多内建变量比如NR表示当前处理到第几行。想输出文件的第100到200行可以awk NR100 NR200 app.logsed是“流式文本编辑器”。它的招牌操作是替换。比如你想把日志里的旧IP全部替换成新IPsed -i s/192.168.1.10/10.0.0.10/g app.log-i是直接修改原文件s是替换g是全局替换每一行里所有匹配到的地方都换。这个命令在生产环境要极其谨慎我的建议是先不加-i跑一遍确认输出没问题再决定是否加上-i真正落盘。追加一个文件备份是更稳妥的做法sed -i.bak s/旧/新/g app.log这样会生成app.log.bak保留原文件出问题可以马上回滚。还有sed -n 5,10p app.log可以只查看第5到10行和awk异曲同工。sort和uniq经常成对出现。sort排序uniq去重但uniq有个特别容易踩的坑它只能去除连续重复的行。也就是说如果重复数据没有排在一起uniq根本去不掉。所以标准用法一定是先sort再uniqsort access.log | uniq -c | sort -rn这个组合的含义是排序、统计每行出现次数、按次数从高到低排序。输出结果是一个非常实用的“频次排行”。我在分析日志里哪个接口被调用最多、哪个IP访问最频繁时用的就是这个组合。3. 组合命令实战从一条命令到一串流水线单一命令是零件组合命令才是产品。这一段我挑三个日常工作中一定会遇到的场景完整展示怎么把哲学变成实战。3.1 经典场景一日志分析与TOP排行假设有一个访问日志access.log每行有一个IP。想统计“访问次数最多的前10个IP”如果你一个个数那得数到天亮。用组合命令是这么干的awk {print $1} access.log | sort | uniq -c | sort -rn | head -10拆开看awk {print $1}提取每行第一列IP地址sort把相同的IP排到相邻位置uniq -c统计每个相邻块的出现次数输出格式是“次数 IP”sort -rn按次数降序排列head -10只取前10行这一条命令就是一条完整的流水线每一步输出的文本流自然成为下一步的输入。我在很多场合把这条命令称为“日志分析第一式”因为它直接解决了“谁在大量访问”“哪个IP最可疑”这类最常见的诉求。有一次线上出现接口异常调用我用这条命令跑了一次发现一个IP的调用量是正常值的上百倍顺藤摸瓜很快就定位到了问题来源。如果想再加一层过滤比如只看状态码为500的请求来自哪些IP可以在awk阶段加条件awk $9 500 {print $1} access.log | sort | uniq -c | sort -rn | head -10这里的$9是日志里状态码所在的列具体列号取决于你的日志格式。第一次不确定列位置时先head -1 access.log看一下格式再数列不要想当然。3.2 经典场景二批量文件处理服务器上经常有成批的文件要统一改名、统一打包。比如有几百个文件叫report_202401.txt、report_202402.txt这样的格式你想全部改成summary_202401.txt。一个文件一个mv会疯掉正确姿势是用循环for f in report_*.txt; do mv $f summary_${f#report_}; done这个命令的关键在于${f#report_}它表示“去掉变量f开头的report_前缀”。写之前我强烈建议你先echo调试一下for f in report_*.txt; do echo mv $f summary_${f#report_}; done把所有动作打印出来确认没有问题再把echo去掉执行。这个“先打印再执行”的习惯能救你无数次尤其是批量操作涉及改名、删除、覆盖时宁可多花10秒钟预览也不要手滑毁掉一批文件。批量打包的场景更常见。比如要把/data/logs下所有7天前的日志文件压缩挪走可以组合find和打包命令find /data/logs -type f -name *.log -mtime 7 -exec gzip {} \;-exec是find的“执行动作”{}会被替换为找到的每个文件名\;表示命令结束。这句的意思是找到7天前的日志依次用gzip压缩。等压缩完成后再用find加-name *.gz把它们移动或者删除都行。这里提醒一句-exec的语法很严格{} \;中间不能乱加空格否则会报错。这也是新手最容易写错的地方。3.3 经典场景三快速定位占用与清理磁盘磁盘满了这是运维日常高频故障之一。处理这类问题我的标准操作流程是这样的第一步确认整体占用情况df -h-h让人可读单位显示。输出里Use%接近100%的挂载点就是重灾区。第二步在重灾区目录下找出最大的文件或目录du -h --max-depth1 /var/log | sort -rh | head -20du统计磁盘使用量--max-depth1只统计一层子目录sort -rh按人类可读大小降序排列。这里有一个要注意的细节du默认会统计所有子目录和文件如果目录层级很深执行会非常慢所以必须指定--max-depth限制深度。第三步定位到具体大文件后如果这个文件还在被进程占用直接删除可能不会释放空间。这时用我之前提过的lsof | grep deleted找出占用进程然后重启该进程或让它关闭文件句柄磁盘空间才会真正释放。我见过不少同事遇到过这样的怪现象文件删了df -h却还是满的就是因为忽略了这个“进程持有已删除文件”的问题。如果只是想快速清理临时文件推荐这一步find /tmp -type f -mtime 3 -delete-delete表示把找到的文件直接删除。这个命令风险极高一定不要轻易扩大范围。我个人的铁律是先不写-delete换成-print跑一遍看到底会删哪些文件确认无误后再加-delete。4. 效率进阶让常用命令变成你自己的武器到这里你已经掌握了单条命令和组合命令的基本功。但要真正拉开效率差距还得学会“定制化”把高频操作封装成别名、脚本让命令行更像你的私人工具。4.1 用alias把高频长命令变成快捷键alias是命令的“快捷方式”。比如你每次都敲ls -lh可以给它起个短名字alias llls -lh这样以后敲ll就等同于ls -lh。但这里有个关键普通敲的alias只在当前终端会话有效关掉就没了。想永久生效得写进shell的配置文件。常见的配置文件是~/.bashrc编辑这个文件在末尾添加alias行然后执行source ~/.bashrc让它立即生效。我建议每个人都建立一套自己的alias体系。下面这个清单是我自己的常用配置可以参考alias llls -lh alias lals -A alias grepgrep --colorauto alias dfdf -h alias dudu -h alias ..cd ..特别说明一下alias grepgrep --colorauto。不加颜色grep匹配到的关键内容在纯黑白终端里一点都不显眼加了颜色匹配内容会高亮显示排查日志时视觉效率提升一大截。同理ls --color也是默认该开的。4.2 从命令到脚本日常重复工作的“一键化”单条命令处理一轮操作很快但如果你每周都要重复做同一件事比如每周一清理一周前的临时文件、把日志归档、发个统计报告这时候就应该把它写成一个脚本。脚本不必一开始写得多复杂思路其实很简单把你在终端里敲过的一串命令原样放进一个文件加上#!/bin/bash开头再给文件加上执行权限就是一个最基础的脚本。举个例子假设你每天要统计日志中ERROR出现的次数并追加到报告文件#!/bin/bash echo ERROR count $(date) /var/log/error_report.txt grep -c ERROR /var/log/app.log /var/log/error_report.txt把这段存为count_error.sh然后执行chmod x count_error.sh ./count_error.shchmod x是给文件增加执行权限没有它对文件直接运行会提示权限不足。后续只需要执行./count_error.sh就能完成整个统计动作。这就是把重复操作“脚本化”的雏形想扩展就往脚本里加命令、加判断、加循环。脚本和单条命令最大的区别在于单条命令是你在场时用的脚本是你不在场时也能跑的。因此脚本里要更注重“健壮性”变量加引号、判断命令是否成功、输出记录到日志。比如前面统计错误数的脚本如果日志文件不存在grep会直接报错并把错误打到屏幕上。但在脚本里屏幕可能是没人的错误信息就丢了。这时候就要加判断if [ -f /var/log/app.log ]; then grep -c ERROR /var/log/app.log /var/log/error_report.txt else echo app.log not found /var/log/error_report.txt fi不要觉得这是多此一举脚本一旦定时运行任何一条小错误都可能让你在事后排查时多花一小时。宁可提前把分支写清楚。4.3 定时任务用crontab把脚本编排起来写完脚本最后一环是让它自动跑。Linux的定时任务由crontab管理。crontab -e这会打开当前用户的定时任务表。每行是一个任务格式是5个时间字段加一个命令5个字段分别表示“分钟 小时 日期 月份 星期”。比如每天早上8点执行刚才那个脚本0 8 * * * /home/user/count_error.sh /var/log/cron.log 210 8 * * *的意思是每天* * *的8点0分执行。 /var/log/cron.log 21是把脚本的输出和错误都追加到一个日志文件里这个习惯极其重要。定时任务的问题在于它不像你手动执行时报错能马上看到所有输出不进日志文件的话出了问题你根本无从排查。crontab排错时有个内置环境变量的问题要留意cron运行命令时的环境和你终端里的环境不一样PATH往往不包含用户自定义目录。所以脚本里凡是需要用到绝对路径的地方一律写全路径不要依赖相对路径更不要依赖~之类在当前上下文可能不生效的符号。我踩过这种坑一开始写cron执行脚本脚本总是报“command not found”加了一堆绝对路径才解决。4.4 用好man、info和版本帮助文档的三个时机再回到文档。很多人觉得文档查起来浪费时间但实际情况恰恰相反查文档浪费10秒瞎试参数可能浪费半小时。我的经验是分三个时机查文档第一明确知道命令但忘了参数直接命令 --help扫一眼就够。第二命令不太熟需要系统了解能力边界man 命令打开看重点看DESCRIPTION和EXAMPLES部分。第三遇到了“明明应该有更高级语法”的需求比如awk需要做求和、sed需要多行处理直接man awk去翻内置函数和语法章节这种系统文档比任何零散教程都完整。还有一个进阶技巧man打开以后按/输入关键词搜索页面内容按n跳到下一个匹配。比如你想知道ls里有关排序的参数在man ls界面里按/sort瞬间定位。这个搜索动作比逐行翻页高效十倍。5. 常见问题与排查技巧实录最后一部分我把过去几年实际工作中经常遇到的Linux命令相关问题和排查心得整理成清单这些内容在教科书里很少看到但每周都可能用到。5.1 “Permission denied”不是只有chmod能解决新人一看到Permssion denied第一反应就是chmod 777。这是最典型的错误操作。先说结论chmod 777能让任何用户读、写、执行这个文件几乎等于把文件锁直接拆了。在很多安全要求高的环境里这就是事故。要正确排查思路应该是按顺序检查第一文件所有者是谁当前用户是谁第二文件权限位是什么第三父目录权限是什么。很多时候你打不开一个文件并不是文件本身权限不够而是它的父目录没有执行权限x导致你无法“穿过”这个目录。我远程帮人排查时最常见的情况是用户把文件chmod 777了还是不行结果发现是上层的某个目录权限是700其他用户根本进不去。正确的做法是用ls -l看文件详细权限用id看当前用户必要的时候用stat看文件的更详细信息然后针对性地调整。比如要把当前用户变成文件所有者sudo chown $(whoami) file.txt然后只需要给当前用户需要的权限比如只读chmod 400 file.txt这才是正常的排障思路而不是一刀切777。5.2 管道命令里“丢了数据”的两大隐患用管道串命令时输出结果不对很多人第一反应是命令写错了但有两类经典坑值得单独拿出来说。第一类是标准错误没有进管道。前面反复强调过管道默认只接标准输出。如果你的上游命令因为某种原因把关键信息写到了标准错误管道下游就什么都收不到。解决方案是显式合并cmd 21 | nextcmd第二类是管道的“失败掩盖”问题。默认情况下一个管道命令的退出码是最后一个命令的退出码不管前面命令失败与否。比如grep 关键内容 app.log | grep 状态码500 | wc -l如果第一个grep因为文件不存在而失败第二个grep可能输入为空wc -l输出0并返回成功。这就导致脚本里以为“没找到关键内容数量为0”实际可能是“日志文件根本没读到”。要严格检查管道中每个环节是否成功可以在shell里开启set -o pipefail这样只要管道里任何一个命令失败整条管道的退出码就是失败。脚本开头加上这行是专业脚本的标志之一。要看“某条命令是否按照预期完成”可以用echo $?查看上一条命令的退出码0代表成功非0代表失败。这是排障的基本功但很多新人根本不会用。5.3 文件名带空格、特殊字符的经典翻车现场Linux文件名里可以有空格可以带各种特殊符号这在实际业务中太常见了。比如你从某个系统导出的文件名是2024 report final.txt你执行cat 2024 report final.txt系统会把这当成三个独立的文件名然后报错找不到2024。这就是没给文件名加引号的后果。正确写法是cat 2024 report final.txt或者用转义字符cat 2024\ report\ final.txt一般原则里凡是文件名作为变量出现的场景一定要加双引号包裹。比如脚本里for f in *.txt; do echo 处理文件: $f done如果$f不加引号遇到带空格的文件名echo就会把它当作多个参数输出虽然大多数情况看起来没差但一旦要执行删除、移动操作就可能出大问题。我的个人习惯是“凡是变量出现的地方就加双引号”宁可多打两个字不冒失去文件的风险。5.4 “命令找不到”却明明装了软件执行某个命令报command not found但软件明明装了最常见的原因是PATH环境变量没有包含该命令的安装目录。比如有些软件安装在/usr/local/mysql/bin这个目录不在PATH里直接敲mysql当然找不到。解决方法有两个要么用绝对路径执行要么把目录追加到PATH。临时追加export PATH$PATH:/usr/local/mysql/bin这个配置在当前会话有效重启终端失效。永久生效就要写进shell配置文件比如~/.bashrcecho export PATH$PATH:/usr/local/mysql/bin ~/.bashrc source ~/.bashrc另外要区分一种情况你可能安装了软件但它是动态链接库形式的并不能直接作为命令执行。比如某些Python包安装后它的可执行文件在~/.local/bin或某个虚拟环境的bin目录下这同样需要把路径加入PATH。判断到底命令在哪个目录可以用which或type来探查which 命令名如果which有输出说明命令在PATH里没有输出说明要么没装要么路径不在PATH里。5.5 “磁盘空间没释放”的排查清单最后再整理一份磁盘满故障的排查清单按顺序走基本能覆盖90%的情况先df -h确认哪个分区满了。du -h --max-depth1逐层确认大目录。定位大目录内的具体大文件用ls -lhS按大小排序查看。检查是否删除但未释放lsof | grep deleted。若被进程占用重启进程或重定向其日志输出。确认释放后再看一次df -h。这套流程我实际执行过无数遍每次都能快速定位到问题根源。最后一次补充一个高频场景程序产生的大量日志如果没有任何轮转机制迟早填满磁盘。遇到这种机器临时清理只是治标治本方案是把日志轮转配置起来。系统自带logrotate可以按天、按大小切割日志并保留最近N份历史。这个工具非常值得单独花时间研究是长期运维的“省心利器”。个人体会讲到这儿Linux命令其实就是一个“越用越顺手”的过程。最初你会对着man手册翻来翻去后来会发现自己开始自然地把命令和管道组合起来再后来会主动写脚本、配alias。每一次卡壳和踩坑最后都会变成你排障经验的一部分。用命令行的过程本质上是在熟悉一种思维方式小工具、大组合、文本为媒、文件为骨。把这种思维焊在脑子里比记住任何一条命令都重要。