尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Linux磁盘空间排查:find与du命令组合实战指南

Linux磁盘空间排查:find与du命令组合实战指南 1. 从一次磁盘告警说起为什么你需要掌握查找大文件的技能那天下午我正在调试一个服务突然收到一条服务器磁盘使用率超过90%的告警。登录服务器一看/home分区已经飘红。这可不是小事服务日志可能无法写入临时文件创建失败甚至整个应用都可能因此挂掉。我的第一反应不是去盲目地删除文件而是必须快速、精准地定位到那些“罪魁祸首”——占用大量磁盘空间的文件。在Linux世界里这几乎是一个运维、开发乃至任何需要与服务器打交道的人的必备生存技能。无论是清理陈年日志、找出异常增长的缓存文件还是简单地给磁盘“瘦身”你都需要一套高效、可靠的命令组合拳。而find和du就是这套组合拳里的核心招式。很多人可能单独用过它们但将find -type f -size和du -a结合起来才能发挥出最大的威力。前者像是一个精准的探测器可以根据文件大小、类型等属性进行过滤后者则像一个尽职的审计员能清晰地汇报每个文件或目录的实际磁盘占用。单独使用任何一个都可能陷入“大海捞针”或者“只见树木不见森林”的困境。这篇文章我就结合自己无数次清理磁盘的实战经验带你彻底搞懂如何用这两个命令黄金搭档快速揪出系统中的“空间吞噬者”。无论你是刚接触Linux的新手还是想优化自己排查流程的老手这里都有你需要的细节和“坑点”预警。2. 理解核心工具find与du的命令哲学与差异在动手之前我们必须先厘清find和du这两个命令的根本区别和设计哲学。这决定了我们在什么场景下该用谁以及如何将它们配合使用。find命令的核心任务是“查找”。它基于你给定的路径遍历目录树并根据你设置的各种测试条件tests和动作actions来筛选和操作文件。它的强大之处在于其丰富的表达式可以按文件名、类型、大小、修改时间、权限等几乎任何元数据进行过滤。当我们使用find -type f -size 100M时我们是在说“请找出所有类型为普通文件-type f并且大小超过100兆字节-size 100M的文件。”find汇报的是文件的“逻辑大小”也就是ls -l命令看到的那种大小即文件内容实际有多少字节。它不关心这个文件占用了磁盘上多少个块因此它的速度通常很快因为它主要读取的是文件的inode信息存储在磁盘特定区域的元数据表。而du命令Disk Usage的缩写的核心任务是“统计磁盘使用情况”。它的目标是计算文件或目录在磁盘上实际占用了多少空间。这里就引出了一个关键概念块大小Block Size。磁盘空间是以“块”为单位进行分配和管理的常见块大小为4KB。即使一个文件只有1字节的内容它在磁盘上也会独占一个完整的块因此du报告的大小会是4KB或系统设定的块大小。这就是为什么du报告的大小通常大于或等于ls -l或find基于的逻辑大小。du -a或--all选项让它不仅列出目录的总大小还列出目录下每一个文件的磁盘使用情况。一个简单的对比实验能让你立刻明白两者的区别# 创建一个内容很少但占用一个块的文件 echo “1” tinyfile.txt # 查看逻辑大小 ls -lh tinyfile.txt # 输出可能为-rw-r--r-- 1 user group 2B Apr 10 10:00 tinyfile.txt # find 也会基于这个2B来判定 # 查看磁盘占用大小 du -h tinyfile.txt # 输出可能为4.0K tinyfile.txt看到了吗一个2字节的文件磁盘占用是4KB。如果你用find -size -4k来查找“小于4KB的文件”这个tinyfile.txt会被找到因为它的逻辑大小是2B。但如果你关心的是“哪些文件浪费了磁盘块”那么du给出的视角才是真实的。所以基本的策略就出来了当你需要根据文件的“真实内容量”进行精确筛选时例如查找大于1GB的日志文件用find。当你需要查看文件或目录“实际消耗了多少磁盘空间”并进行排序清理时用du。而更高级的用法则是将find的精准筛选能力与du的详细统计能力相结合。3. 精准狙击使用find -type f -size定位特定大小文件find命令在查找大文件场景下其威力主要体现在-type和-size这两个选项的灵活组合上。我们先来拆解它的标准语法和那些容易踩坑的细节。基础命令格式find 搜索路径 -type f -size 大小范围搜索路径从哪里开始找。可以是.当前目录、/home指定目录或/整个根文件系统需谨慎且可能需要sudo权限。-type f指定查找对象为“普通文件”。这是非常关键的一步可以排除目录、符号链接、设备文件等让我们专注于真正占用内容空间的文件。如果你想包含目录可以去掉-type f或使用-type d单独找目录。-size 大小范围核心过滤器。范围写法有讲究。大小范围的语法详解与易错点-size参数接受的单位包括c字节bytesk千字节Kibibytes 1024字节。注意find手册页明确说明k是1024字节而非1000。M兆字节Mebibytes 1024 * 1024字节G吉字节Gibibytes 1024 * 1024 * 1024字节范围表示100M查找大于100MB的文件。-100M查找小于100MB的文件。100M查找大小恰好等于100MB的文件几乎用不到因为很难恰好相等。实战示例与进阶技巧查找当前目录及子目录下所有大于500MB的*.log日志文件find . -type f -name “*.log” -size 500M这里结合了-name选项进行模式匹配非常实用。找到后你可能想直接查看一下这些文件的末尾确认其内容find . -type f -name “*.log” -size 500M -exec tail -n 5 {} \;-exec选项允许对找到的每个文件执行一个命令。{}是占位符代表当前找到的文件路径\;是命令结束的标记。查找/var目录下所有大于1G的文件并显示它们的详细信息大小、权限、时间find /var -type f -size 1G -exec ls -lh {} \;或者使用-ls动作比-exec ls -lh更高效是find内置动作find /var -type f -size 1G -ls这个命令会输出类似ls -l的格式并包含inode号信息非常全。一个常见的“坑”时间与大小的组合查找。假设你想找出/tmp目录下在最近7天内被修改过并且大小超过100MB的文件可能是某些程序异常产生的临时大文件find /tmp -type f -mtime -7 -size 100M-mtime -7表示修改时间在7天以内。-mtime 7则表示7天以前。这个组合能帮你快速定位近期产生的“可疑”大文件。 注意在根目录/下运行find命令尤其是带有-exec或-delete删除操作时务必极度谨慎。一个错误的表达式可能会匹配到系统关键文件。建议先在不带破坏性操作的命令如单纯-ls上验证结果或者先从特定的用户目录如/home、/var/log开始排查。4. 全局审计使用du -a进行磁盘使用情况排序与分析如果说find是狙击步枪那么du就是战场雷达它能给你整个磁盘空间的全局视图。单独使用du -a会列出所有文件和目录的大小信息量巨大不利于分析。因此我们几乎总是需要结合排序工具sort和头部显示工具head来提取最有价值的信息。经典组合命令找出当前目录下最大的10个文件或目录du -ah . | sort -rh | head -n 10让我们分解这个管道|操作du -ah .-a显示所有条目包括文件和目录。-h“人类可读”格式用K、M、G等单位显示大小而不是纯字节数。这是让结果直观的关键。.当前目录。你可以替换成任何路径如/home/user。输出是每行一个条目格式如“4.0K ./file1”。sort -rh-r反向排序从大到小。-h识别人类可读的数值如2K, 1G并进行正确的大小排序。这是另一个关键点如果不用-hsort会按字符串字典序排序导致“10K”排在“2M”前面因为‘1’比‘2’小这显然是错误的。head -n 10只显示前10行结果。这个命令的变体与应用场景仅查找最大的文件排除目录有时候目录的大小是其下所有文件大小的总和会干扰我们找到单个大文件。我们可以先用find列出文件再用du统计。但更直接的方法是结合find的-type f和-execfind . -type f -exec du -h {} | sort -rh | head -n 10这里-exec du -h {} 与-exec du -h {} \;的区别在于会将尽可能多的文件路径作为参数一次性传给du命令效率远高于对每个文件单独执行一次du命令\;方式。这个命令能直接输出当前目录下最大的10个文件。深入分析特定大目录当du -ah . | sort -rh | head显示某个目录比如./cache/特别大时你可以直接进入该目录或者将路径作为du的参数进行递归分析du -ah ./cache/ | sort -rh | head -n 20查看目录本身的大小不递归子项使用-ssummarize选项。这在快速查看一级子目录的占用时非常有用du -sh /home/* | sort -rh这条命令会清晰列出/home下每个用户目录的总大小并排序让你一眼看出哪个用户的文件最占空间。 实操心得du命令在遍历包含大量小文件或特殊文件系统如网络挂载NFS、/proc、/sys的目录时可能会非常慢甚至因权限问题产生大量错误输出。建议使用--exclude选项排除无关目录或者用2/dev/null忽略错误信息du -ah --exclude“./.cache” --exclude“./node_modules” . 2/dev/null | sort -rh | head -n 15另一个重要提示du统计的是磁盘占用如果文件被硬链接了多次du可能会重复计算其大小取决于du的版本和选项。而find基于inode不受硬链接重复计算的影响。5. 强强联合组合find与du的高级排查策略在实际的复杂排查场景中单独使用find或du往往不够。我们需要将两者的优势结合形成更精细的排查策略。下面我分享几个经过实战检验的高级组合技巧。策略一先定位再评估——找到特定类型的大文件并评估其磁盘影响假设我们怀疑是Docker的镜像和容器数据占用了大量空间。Docker通常将数据存储在/var/lib/docker。我们可以这样做使用find精准定位所有大于100MB的文件sudo find /var/lib/docker -type f -size 100M -ls /tmp/large_docker_files.txt这里用了-ls并重定向到文件是为了保存一个详细的列表供后续分析。sudo是必需的因为/var/lib/docker通常属于root用户。使用du评估这些文件的总影响 我们可以对上一步找到的文件列表进行磁盘占用汇总。但更巧妙的方法是让find直接为du生成参数列表sudo find /var/lib/docker -type f -size 100M -exec du -ch {} | tail -n 1这个命令的妙处在于-exec du -ch {} 对找到的所有大文件执行du -c生成总计和-h人类可读。| tail -n 1du -c会在最后一行输出所有参数文件的总大小。tail -n 1正好把这行总计抓取出来。 输出可能是“总计 15G”。这样你立刻就知道了所有大于100MB的Docker文件总共占用了15GB空间对清理的预期效果有了量化概念。策略二空间回收潜力分析——找出可安全删除的陈旧大文件清理磁盘时我们不仅关心“大”还关心“老”和“是否重要”。/tmp、/var/tmp或一些缓存目录下的陈旧大文件往往是安全的清理目标。# 查找 /tmp 下超过30天未访问且大于50MB的文件 find /tmp -type f -atime 30 -size 50M -exec ls -lh {} \;-atime 30访问时间在30天以前。注意是“访问时间”不是修改时间。有些日志文件可能经常被写入修改时间新但很久没人读访问时间旧。找到后可以手动检查这些文件如果确认无用可以将-exec ls -lh替换为-delete进行删除。再次警告-delete操作前务必先确认策略三应对“幽灵空间”——当du和df报告不一致时你可能遇到过这种情况du -sh /统计的根目录总空间远小于df -h显示的磁盘已用空间。这通常是因为有文件被删除后其进程仍持有该文件的句柄导致磁盘空间并未真正释放。这些文件在find和du的常规扫描中是“看不见”的。此时需要检查已删除但未释放的文件deleted but not released# 查找被进程占用但已删除的大文件 sudo lsof 2/dev/null | grep ‘(deleted)’ | awk ‘{print $NF}’ | sort | uniq | xargs ls -lh 2/dev/null | grep ‘G\|M’ | head -20或者更精准地直接看哪些进程持有了这些文件sudo lsof L1 # 列出链接计数为1的文件通常就是已删除的找到持有这些文件的进程后重启相应进程空间就能被释放。这是find和du无法直接解决的深层次问题但在磁盘空间排查中至关重要。6. 实战案例一次完整的磁盘空间异常排查流程让我们模拟一个真实的场景一台Web服务器磁盘使用率在短时间内飙升到95%。报警响起你需要快速响应。第一步快速定位占用最高的分区和目录df -h # 确认是哪个分区快满了假设是 /home cd /home du -sh * | sort -rh | head -5假设发现是用户www-data的目录异常大。第二步深入异常目录定位具体文件类型cd /home/www-data # 先看最大的子目录是什么 du -sh ./* | sort -rh | head -5 # 假设发现是 ./application/logs 目录巨大 cd ./application/logs第三步使用组合命令找出罪魁祸首# 方案A直接找出最大的文件 find . -type f -exec du -h {} | sort -rh | head -10 # 方案B如果怀疑是某种特定日志比如 access.log find . -type f -name “access.log*” -size 100M -ls # 可能会发现 access.log.1, access.log.2.gz 等都很大第四步分析文件内容决定处理方式# 查看最大的几个日志文件的末尾确认其内容 tail -n 100 最大的文件路径 # 如果确认是历史日志可以考虑压缩归档或删除 # 例如保留最近7天的日志压缩7天前的 find . -type f -name “*.log” -mtime 7 -exec gzip {} \; # 或者如果使用了 logrotate检查其配置是否正常 cat /etc/logrotate.d/your-app第五步处理与验证# 执行清理操作后再次查看空间 cd /home du -sh www-data df -h /home 踩坑记录在一次排查中我发现du -sh显示一个目录只有2G但df显示该分区已用空间莫名少了20G。最终用lsof | grep deleted发现是一个巨大的Java应用日志文件被rm删除后因为JVM进程仍在运行并持有该文件句柄空间并未释放。解决方案不是重启服务器而是向JVM进程发送信号如kill -HUP pid让其重新打开日志文件或者清空该文件echo “” /proc/pid/fd/fd_num这比盲目重启服务更优雅。这个案例告诉我们磁盘空间问题有时是“立体”的需要结合进程、文件系统知识综合判断。7. 编写脚本与自动化监控建议手动敲命令适合临时排查但对于需要定期清理或监控的环境将其脚本化是更专业的做法。一个简单的清理脚本示例清理指定目录下超过30天且大于100MB的日志文件#!/bin/bash # cleanup_old_large_logs.sh TARGET_DIR“/var/log/myapp” LOG_FILE“/var/log/cleanup.log” DAYS30 SIZE“100M” echo “[$(date)] Starting cleanup in $TARGET_DIR” $LOG_FILE find “$TARGET_DIR” -type f -name “*.log” -mtime $DAYS -size $SIZE -ls $LOG_FILE 21 # 先记录找到的文件 find “$TARGET_DIR” -type f -name “*.log” -mtime $DAYS -size $SIZE -delete $LOG_FILE 21 # 再执行删除并将操作记录到日志 echo “[$(date)] Cleanup completed.” $LOG_FILE将这个脚本加入crontab即可实现定期自动清理。务必先在测试环境验证脚本逻辑并确保日志记录功能完好以便追溯删除了哪些文件。对于监控你可以创建一个简单的磁盘检查脚本在空间超过阈值时自动运行排查命令并将结果发送给你如通过邮件、钉钉、企业微信机器人#!/bin/bash THRESHOLD90 USAGE$(df /home | awk ‘NR2 {print $5}’ | sed ‘s/%//’) if [ $USAGE -gt $THRESHOLD ]; then SUBJECT“警告服务器 /home 分区使用率 ${USAGE}%” # 运行我们的排查组合拳将结果存入变量 TOP_FILES$(cd /home du -ah . 2/dev/null | sort -rh | head -n 15) LARGE_FILES$(find /home -type f -size 500M -ls 2/dev/null | head -n 20) # 将信息组合成报告 REPORT“分区使用率${USAGE}%\n\n占用最大的15个文件/目录\n${TOP_FILES}\n\n大于500MB的文件列表\n${LARGE_FILES}” # 这里可以接入发送通知的命令例如 mail 或 curl 调用webhook echo -e “$REPORT” | mail -s “$SUBJECT” adminexample.com fi掌握find和du的深度用法并形成自己的排查套路和自动化策略能让你在面对磁盘空间告警时从容不迫。记住关键不是记住所有命令参数而是理解其背后的原理逻辑大小 vs 磁盘占用、块大小、inode并根据实际情况灵活组合。每次清理前做好确认重要数据备份后再操作你的Linux系统磁盘管理能力就能从“会用”提升到“精通”的层次。
返回列表