做了这么多年运维和开发,发现一个有意思的现象:网上Linux命令的文章一抓一大把,但大家搜来搜去,日常碰到的问题翻来覆去就那么几个。前六篇我们把用户管理、文件操作、进程控制这些基础打完了,这一篇我打算换个思路,不按命令字母表硬排,而是直接把工作中最高频、最容易出事的场景拎出来,以解决实际问题为主线,把那些常用命令揉碎了讲。比如为什么find一跑就把机器卡死、rm删除后怎么恢复、scp传文件到一半断了怎么办、磁盘IO被打满从哪里查起——这些都是群里的兄弟踩过坑之后问得最多的问题,也是面试官最爱拿来出题的考点。
这篇内容会稍微有些长,建议先收藏再慢慢读。不管你是刚接手服务器的新手运维,还是被临时拉去排查问题的后端开发,又或者是准备面试的候选人,把这篇里涉及的命令和思路过一遍,实际干活的时候会顺手很多。
1. 文件查找与磁盘占用:小心你的find和rm
1.1 find查找命令的完整用法与性能陷阱
find是Linux里最强大的文件查找工具,没有之一。但正因为强大,很多人的用法其实是有问题的。
最基本的语法是find [路径] [表达式],路径就是你要从哪里开始找,表达式就是查找条件。举个例子,我想找出/etc目录下所有后缀为.conf的文件:
bash复制find /etc -name "*.conf"
这个命令看起来简单,但里面藏着两个大坑。第一个坑是通配符的转义,-name后面的*.conf建议加上引号。你直接写find /etc -name *.conf在某些shell环境下,如果当前目录刚好有匹配的文件名,shell会在find执行前就把通配符展开,导致find收到的参数变成一堆具体文件名,结果完全不对。所以我习惯一律写成find /etc -name "*.conf",稳妥。
第二个坑是性能。find / -name "xxx"这种全盘扫描,在生产环境的机器上执行,很容易把磁盘IO直接拉满,导致线上服务卡顿甚至超时。我之前遇到过一起事故,同事想找一个配置文件,直接在根目录执行了全盘find,结果数据库所在主机的IO被打爆,业务接口大量超时报警。所以我现在养成一个习惯:查找前先想清楚范围,能用find /home就不用find /,能限定目录层级就加-maxdepth参数。
按时间维度查找也是日常高频场景,比如查最近7天内被修改过的文件:
bash复制find /var/log -mtime -7
-mtime表示修改时间,后面的数字加减号有讲究:-7表示7天以内,+7表示7天以前,直接写7就精确表示第7天当天。类似的还有-atime(访问时间)、-ctime(状态变更时间)。还有一个参数是-mmin,按分钟来计算,排查问题的时候用得比较多,比如“这10分钟内哪个文件被动了”:
bash复制find /app -mmin -10
如果按文件大小查找,常见面试题“找出大于100MB的文件”:
bash复制find / -type f -size +100M
这里的单位很关键,M是MB,G是GB,k是KB,注意小写k。+100M表示大于100MB,-100M表示小于100MB,不带符号就是精确等于100MB。
find还有一个高频组合是配合-exec执行操作,比如一键清理7天前的日志备份:
bash复制find /data/backup -name "*.tar.gz" -mtime +7 -exec rm -f {} \;
这里{}代表find找到的每一个文件,\;是-exec命令的结束标记。需要注意这里的分号和反斜杠不能丢,丢了会直接报错。用-exec有个潜在风险:如果文件数量特别多,会逐条执行命令,效率偏低,更推荐用管道配合xargs:
bash复制find /data/backup -name "*.tar.gz" -mtime +7 | xargs rm -f
但xargs有个天坑:如果文件名里有空格或特殊字符,会被错误拆分。稳妥的写法是:
bash复制find /data/backup -name "*.tar.gz" -mtime +7 -print0 | xargs -0 rm -f
-print0和-0搭配,用空字符作为分隔符,就能完美兼容带空格的文件名。这个细节很多人不知道,操作线上服务器时不小心就会踩雷。
1.2 du和df:磁盘空间到底被谁吃掉了
排查磁盘空间不足,第一步用df看整体情况:
bash复制df -h
-h是人性化显示,会自动把字节数换算成G、M这种单位。输出的第一列是文件系统,最后一列是挂载点,重点看/根分区和/home这种可能单独分区的挂载点有没有被打满。
df看到的是文件系统层面的总空间,但要查具体是哪个目录占了大头,就得靠du了。du默认会递归统计所有子目录的大小,所以直接du -sh /会很慢,通常的做法是先看一级目录:
bash复制du -sh /* 2>/dev/null | sort -rh | head -20
-s表示只汇总每个参数目录的总大小,-h人性化显示,sort -rh按人类可读的数字反向排序,head -20只取前20行。这样一趟下来,哪个目录是空间杀手一目了然。
像/var/log下面日志文件积累导致根分区满,用这个命令组合几分钟就能定位。需要注意的坑是du会真实读取所有文件元数据,在IO已经紧张的情况下执行,会暂时加重负载,建议低峰期排查。
还有一种情况:df -h显示空间剩余很多,但应用却报“磁盘空间不足”,那大概率是inode用完了。检查inode的命令是:
bash复制df -i
如果IUsed一列的百分比接近100%,就是大量的小碎文件占满了inode,最经典的场景是邮件队列、缓存目录和docker的存储目录堆积了大量小文件。处理方式是找到对应目录,清理掉那些没用的临时文件,然后用df -i确认恢复。
1.3 rm删除命令的安全操作与误删恢复思路
rm -rf被戏称为“删库跑路专用命令”,不是没道理的。我见过太多人敲完rm -rf /var/log/nginx/之后发现路径多打了个空格,变成了rm -rf /var/log/nginx /。这种惨案的根源是:rm命令本身没有“回收站”概念,删了就是真的没了,ext4和xfs文件系统下常规手段基本没法恢复。
所以我的建议有三条,可以说都是血泪经验换来的。
第一条,删除之前先ls确认。把这个习惯刻进肌肉记忆:
bash复制ls -ld /data/old_app
rm -rf /data/old_app
第二条,能用mv替代就尽量用mv。把要删的目录先移动到一个临时trash目录,观察几天,确认业务没依赖了再真正删除:
bash复制mkdir -p /data/.trash
mv /data/old_app /data/.trash/
第三条,重要数据务必做异地备份。rm误删之后,如果文件被进程持续占用,可以用lsof找回部分数据,比如:
bash复制lsof | grep deleted
然后到/proc/<pid>/fd/目录下找到对应的文件描述符,复制出来恢复。但这属于“死马当活马医”的办法,操作复杂且依赖进程存活,不能当作常规手段。真正安全的策略永远是备份先行。
提示:线上环境执行任何批量删除命令,建议先加上
-v参数打印删除日志,并且用find先统计一下数量,不要闷头一把梭。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文本处理三剑客:grep、sed、awk的实战玩法
2.1 grep筛选日志:比你想象中更能打
grep应该是Linux下使用频率最高的命令了。常规用法是grep 关键词 文件名,但实际日志分析中,很多人只会这一步,浪费了这个工具一大半的能力。
最常用的几个参数:
bash复制grep -i "error" app.log # 忽略大小写匹配
grep -r "TimeoutException" /app/logs/ # 递归搜索整个目录
grep -n "ERROR" app.log # 显示匹配行行号
grep -v "heartbeat" app.log # 反向匹配,过滤掉不需要的行
grep -c "ERROR" app.log # 统计匹配行数
grep -A 5 -B 5 "NullPointerException" app.log # 显示匹配行的后5行和前5行
-A和-B这两个参数在排查报错时特别有用。比如你在日志里看到一条异常堆栈,只看报错那一行根本无从下手,带上上下文才能还原当时的代码执行路径。
grep处理多文件时,可以在文件名前加-H强制显示文件名,或者用--include限定文件类型:
bash复制grep -r "orderId:12345" /app/logs/ --include="*.log" -l
-l表示只列出包含匹配内容的文件名,而不输出具体匹配行。这个在“日志分散在多个滚动文件里,想知道哪个文件出现了某条记录”时极其好用。
要注意一个grep的经典误区:处理大文件时,grep本身很快,但如果你的正则写得太
