Linux 上线跑一段时间后新装一台机器第一件事我永远是先ls /看一遍。你可能会觉得这有什么好看的无非就是 bin、etc、usr 那几套。但说真的很多干了几年运维的人被问起“/usr 是干嘛的”都得愣一下更别提遇到磁盘写满、命令找不着、软件装上跑不起来这类问题时的慌乱样了。Linux 目录结构全解析是个老生常谈的话题可越基础的东西越值得反复琢磨。目录结构不只是让你记住每个目录叫什么它背后是一整套系统设计的哲学什么东西放哪、什么数据可变、什么文件能删、什么目录重启就没了。把这些弄明白你在排查问题时能少走很多弯路也好理解为什么网上那些“优化脚本”动不动就让你清空这个目录、删除那个文件——有些是合理的有些就是在坑你。这篇文章我会从设计标准、核心目录拆解、实际运维场景、常见问题四个角度把我这些年跟目录打交道踩过的坑和攒下来的经验一次说清楚。1. 先搞清楚Linux为什么长这样目录体系的设计思路与标准很多人第一次接触 Linux 目录结构时脑子里都是乱的为什么/bin和/usr/bin里都有ls为什么有的目录是空的为什么/proc里全是数字文件夹要理解这些得先弄清 Linux 目录体系不是哪个工程师拍脑袋定的而是有统一规范的。1.1 FHS 标准到底在管什么FHS全称 Filesystem Hierarchy Standard翻译过来就是“文件系统层级标准”。它的核心目标是让所有类 Unix 系统在目录组织上保持一致的风格这样你从一台发行版换到另一台或者从一套大型机迁到一个小服务器都能快速找到配置文件、日志、程序所在的位置。FHS 并不强制每个目录里放什么文件它规定的是哪些目录必须存在、它们的定位是什么、彼此之间什么关系。比如它明确规定/bin存放的是“系统最基本的用户命令”/etc放“本机配置文件”/var放“会变大的运行数据”。你把这几个目录定位吃透后面所有问题都迎刃而解。不同发行版之间存在一些细微差异——比如RHEL/CentOS 系和 Debian/Ubuntu 系在/lib、/usr/lib的处理上就有些不一样——但大框架都是遵循 FHS 的。所以学一套走遍各发行版都不慌。1.2 三个维度看懂任何目录要快速判断一个目录是干嘛的我总结了三个维度可共享还是不可共享、可变还是静态、系统必需还是用户可选。可共享的目录比如/usr、/opt可以放在网络文件系统上让多台机器共用一套程序不可共享的比如/etc、/boot每台机器都必须有自己的副本因为里面的配置和内核是针对特定主机的可变的目录比如/var、/tmp里面的数据会持续增长或频繁刷新静态的比如/usr、/lib安装完系统之后基本不再变化除非你升级软件包。把这个矩阵画出来你看任何目录都能快速归类。比如/var/log就是“不可共享可变”而/usr/share就是“可共享静态”。分区规划时非常依赖这个分类因为它直接决定了哪些数据需要单独挂载、哪些数据必须天天备份。我还见过一种更实用的看法Linux 的目录结构本质上是在做存取隔离——程序文件放/usr和/bin配置放/etc运行过程产生的临时数据放/tmp和/run持久化的状态数据放/var/lib。这就像家里做饭刀和锅放厨房油盐酱醋放调料架吃剩的菜放冰箱当然不能把刀扔床底下去。2. 核心目录逐个拆解从根目录到临时目录一次说明白目录结构这东西光看理论没意思得真正走进每一个目录里翻一翻。下面我会按实际使用频率和重要性把这几个最核心的目录挨个拆开讲。不光是“这个目录叫什么”更重要的是“里面出了问题会怎样”。2.1 根目录与系统启动链条/bin、/sbin、/boot、/lib/是整个文件系统的大树根所有目录都从它分叉出去。但真正的秘密藏在根目录下的几个子目录里。先看/bin和/sbin。历史原因早期 Unix 系统会把系统启动时必须用到的基础命令单独放在/bin把需要 root 权限才能执行的系统管理命令放在/sbin。现在的发行版大多数已经把/bin、/sbin做成了/usr/bin、/usr/sbin的符号链接也就是说你看到的/bin/ls其实就是/usr/bin/ls。这是为了把根分区做得尽量小让更多内容统一收到/usr下。理解这一点你才不会被“为什么两个目录都有一堆命令”的现象整懵。/boot目录里装的是内核镜像比如 vmlinuz 开头的一堆文件、initramfs 镜像和引导加载程序的配置文件。简单说机器通电后固件先加载引导程序引导程序再去/boot里找内核。有些新手手贱去清“大文件”把/boot里内核文件删了重启直接进不了系统这种事我见过不止一次。这个目录基本不用动更新内核要靠安装包管理器统一处理。/lib和/lib64在传统布局里是放系统启动阶段需要的共享库文件现在各主流发行版同样把它们链接到了/usr/lib和/usr/lib64。当你下载一个绿色版软件运行时报“cannot open shared object file”十有八九就是程序依赖的.so动态库不在这些目录的搜索路径里。2.2 配置、运行与设备/etc、/var、/dev/etc是 Linux 系统里我最敏感的一个目录因为它存放了几乎所有服务的配置文件。从网卡的配置、DNS 设置到 SSH 服务端配置、用户组信息全都在这。在这个目录里改错一个字段轻则某个服务起不来重则整机开不了机。拿最常见的例子说/etc/passwd里记录了用户账户/etc/shadow里存密码哈希/etc/ssh/sshd_config控制 SSH 登录策略/etc/sysctl.conf是内核参数配置。我强烈建议你在动这些文件之前先备份哪怕只是cp一份带个后缀。/var是“会变大”的目录其中/var/log和/var/lib最典型。所有服务运行时的日志都打在/var/log下系统排错首先翻这里软件运行时产生的状态数据比如数据库的文件、软件包的元数据在/var/lib下。这个目录经常是磁盘空间告急的元凶我们后面实操环节会专门聊怎么排查。/dev是设备文件的存放点。Linux 里一切皆文件硬盘、U 盘、终端、声卡在/dev下都以文件形式呈现。比如/dev/sda代表第一块硬盘/dev/tty0是当前终端。你平时做磁盘分区、挂载操作时认的就是这些设备节点。2.3 用户目录与软件资源/home、/root、/usr、/opt/home是普通用户的家目录所在地每个用户一个子目录用户的个人文件、配置、缓存都在里面。/root是管理员的家目录普通用户一般无权访问因为它的权限是 700。很多人一看到/usr就以为是“用户目录”这是一个经典误区。/usr全称其实是 Unix Software Resources它是系统里软件资源的核心存放区。你可以把它看作整个系统软件的“第二根目录”/usr/bin放可执行程序/usr/lib放库文件/usr/share放与架构无关的共享数据比如文档、图标、时区信息。刚接触 Linux 开发的人更容易混淆的是/usr/local。这个目录是给管理员手动编译安装的软件用的FHS 规定/usr/local应当独立于系统的软件包管理器。你自己./configure make make install装出来的程序默认就是进这里。这样做的最大好处是就算你哪天把系统自带的软件搞崩了/usr/local里的东西一般不受影响。/opt是给第三方大型软件准备的比如某些商业软件、集成开发环境它们会把独立的目录放到/opt/软件名下。相比普通安装方式这套布局的好处是卸载时只要删掉对应目录就能清干净。2.4 虚拟文件系统与临时目录/proc、/sys、/run、/tmp这四个目录是新手最容易产生鬼打墙感觉的地方。先说/proc它是一个不占用磁盘空间的内存虚拟文件系统内核把运行中的信息实时映射到这里。/proc/cpuinfo里能看到 CPU 型号/proc/meminfo里有物理内存状态每个进程运行时的数据在/proc/进程号下。你在里面看到的所有文件大小都是 0因为内容本身就是动态产生的也正因如此du统计磁盘空间时它会自动被忽略。/sys和/proc类似但它更侧重内核设备模型和驱动信息比如查看和管理硬件属性。/run是一个 tmpfs内存文件系统存的是系统启动以来创建的运行时数据比如 pid 文件、socket 文件重启后清空千万别在里面放持久化内容。/tmp大家用得最多它是所有用户都能写的临时目录。但要注意两点第一系统可能定期清理里面太久没动过的文件第二它具备 sticky bit 特性表现在目录权限的 others 部分是 t意思是你能在自己的文件里随便删但删不了别人的。不少事故案例就是有人没搞清楚这点试图在/tmp里维护什么持久数据结果重启后全没了。3. 把目录结构用进实际运维和开发场景知道每个目录是干嘛的只是入门真正有价值的是在目录出问题时知道怎么处理。我会带你走三个最常见的实战场景把前面讲的目录知识串起来。3.1 磁盘空间不够时先查哪几个目录生产环境最容易遇到的告警就是磁盘空间不足。遇到这个情况我一般不是直接rm -rf一个看着很大的目录而是按顺序做三步定位。第一步用df -h看哪块分区满了。比如根分区/满了而/data还很空说明要清理目标在根分区下面。第二步用du -sh /*或对/var、/usr等大目录单独执行从根目录往下逐层找看哪个目录占用最大。第三步进到占用最大的目录里再用du -sh * | sort -rh | head -20排行揪出元凶。# 查看各分区整体使用情况 df -h # 统计根目录下每个一级目录的占用便于定位 du -sh /* 2/dev/null | sort -rh # 深入某个目录比如最常见的/var继续定位 du -sh /var/* 2/dev/null | sort -rh根据我经手的案例/var/log里疯狂增长的某个服务日志是最普遍的原因其次是/var/lib下数据库文件的膨胀还有/tmp下没有被正确清理的临时文件。记住du看到的是文件占用的块大小不是文件逻辑大小两者在稀疏文件等特殊场景下会不一致。3.2 环境变量PATH配置中的目录角色新人经常遇到的另一个问题是明明软件装了在终端里敲命令却提示 command not found。这时候就要检查 PATH 环境变量。PATH 是一个目录列表系统按照顺序去这些目录里找可执行文件。用whereis或which可以看某个命令的真实路径。比如which python3返回/usr/bin/python3说明它是在标准系统目录里的。但如果你手动编译装到了/usr/local/bin而你的 PATH 里没有包含这个路径那命令就找不到。# 查看当前PATH里有哪些目录 echo $PATH # 临时追加目录 export PATH$PATH:/usr/local/mytool/bin # 永久写入用户配置文件 echo export PATH$PATH:/usr/local/mytool/bin ~/.bashrc source ~/.bashrc把命令放到/usr/local/bin的好处是它通常在 PATH 里比/usr/bin更靠前所以你编译安装的新版本会自动覆盖同名的系统版本。这也解释了为什么我们用包管理器升级过的软件有时候不生效——很可能 PATH 的前面藏着另一个目录里的同名旧命令。3.3 部署软件时文件该放哪里目录落位思路部署一个新服务的时候你要考虑的不只是“能不能跑起来”还有“维护的时候方不方便”。不同安装形式对目录的落位有很大差别用包管理器apt、yum、dnf安装的软件会按照发行版约定自动分散到/usr/bin、/etc、/var/lib、/var/log里好处是升级方便、依赖关系清晰手动编译安装的软件默认进/usr/local相关文件集中在/usr/local/bin、/usr/local/etc等子目录卸载时直接删除对应目录即可厂商提供的绿色软件包常常解压到/opt下自己的独立目录然后/opt/xxx/bin里放启动脚本容器和虚拟环境的方式则完全没有固定目录概念镜像内部自成一套我们只要做好目录挂载映射即可。一份软件装好之后它往往同时会在静态区/usr和可变区/etc、/var落脚。做备份时千万不要只盯着一处更要重视/etc下对应服务配置文件的备份。4. 常见问题与排查技巧实录最后这部分我整理了几组高频出现的问题和排查思路遇到同类情况可以直接照着查。4.1 磁盘空间不足的隐藏杀手被删除但仍被占用的文件这是一个让很多人头疼的场景df -h明明显示根分区用了 95%但du -sh /一圈跑下来把所有文件加起来空间占用远没有那么大。这时候十有八九是有进程打开了一个文件随后文件被删除但进程还在写它的句柄所以磁盘空间没释放。排查方法是用lsof找带 deleted 标记的文件。# 列出所有已删除但仍在打开中的文件并查看它们占用的空间 lsof | grep deleted # 如果明确某个目录下挂了服务可以针对性过滤 lsof L1 /var/log | grep -i deleted找到对应的 PID 后重启相关进程或者整服务空间就释放了。注意千万不要在生产环境上直接盲目 kill 进程先确认是什么服务评估影响面再动手。4.2 inode 耗尽导致“磁盘还有很多但文件写不进去”有些场景下明明df -h显示空间还有几十 G但创建文件时系统提示 “No space left on device”。这时候要看df -i因为 Linux 文件系统除了限制大小之外还限制 inode 数量。inode 说白了是文件系统的“户口本”每个文件都要占有一条记录。当磁盘里堆积了大量小文件比如临时缓存、Swoole 运行的 socket 文件、邮件队列等inode 被耗光磁盘再空也写不了新文件。# 查看inode使用率 df -i # 找到某个目录下海量小文件的具体位置结合文件数量定位 find / -xdev -type f | wc -l解决思路很直接删除无用的小文件或者找到罪魁祸首目录做清理。如果某个应用本身就是高频创建临时文件的类型那就得考虑把它的临时目录挂载到 tmpfs 上直接在内存中读写避免对磁盘 inode 的消耗。4.3 改了 /etc 下的配置导致服务起不来或系统进不去这是每个运维必会上的一课。有一次我修改了/etc/sysctl.conf想着调大某个内核参数结果重启之后服务直接起不来了。排查到最后发现是参数格式写错了内核拒绝加载。遇到这类问题别慌按下面几步走如果只是某个服务起不来先用systemctl start 服务名查看错误输出再查看/var/log/messages或/var/log/syslog里的相关记录如果系统完全进不了图形界面或网络起不来可以尝试进入单用户模式或救援模式把出问题的配置先改回来从今往后养成好习惯改任何一个/etc下的核心配置之前先做好备份。我习惯用cp保留一个带日期的原始版本比如cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.20240101。在/etc上还有一条必须记住很多软件在升级时会检查配置文件的哈希值如果它发现你手动改过可能不会直接覆盖你改完的文件而是生成一个.rpmnew或.dpkg-dist新文件让你自己合并。看到这类文件别觉得奇怪它其实是系统在保护你的自定义配置。4.4 临时目录、日志目录增长过快怎么有效治理日志目录无限增长是新手最容易忽略的问题。处理思路并不是“扛到满了再删”而是从一开始就做好轮转与限制。logrotate是绝大多数发行版自带的日志轮转工具它按配置定期切割日志、压缩、删除旧文件。你可以修改/etc/logrotate.d/下的配置来控制某些日志的保留频率和份数。例如对某个应用我们希望日志一天切一次保留 7 份就可以写一段配置/var/log/myapp/*.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }这样即使日志暴涨磁盘空间也会被限制在一个可控范围。如果你嫌logrotate麻烦还可以直接在应用程序内部开启按大小切割日志的选项比如 Nginx、Tomcat 等都有对应配置。4.5 目录权限与使用者混淆导致的权限拒绝最后说一个很容易踩的坑即使你的文件在/usr/local/bin里、路径也在 PATH 里但你执行不了。这往往是因为权限设置不合理。一个可执行文件必须至少满足两个条件文件自身有 x 权限以及调用者的身份能穿过文件所在目录的权限限制。我用ls -l查看一个项目演示脚本的时候经常发现有人手工vim创建出来的脚本权限是 644也就是没有执行权限。这时候直接chmod x 脚本名即可。但要注意如果目录权限有问题比如某个中间层目录是 700其他用户永远无法进入普通用户执行同一个脚本时依然会报 Permission denied。# 查看文件权限 ls -l /usr/local/bin/xxx # 给脚本加执行权限 chmod x /usr/local/bin/xxx # 查看目录权限确定可穿越 ls -ld /usr /usr/local /usr/local/bin很多人只记住了chmod 777这个万能解但生产中我真的不建议随手用 777因为它把所有用户都变成了可读可写可执行任何非授权用户都能篡改你的程序文件安全风险极大。更合理的做法是文件归属某个用户目录按需给组或其他人开权限执行位只给需要的使用者开。最后再分享一个小技巧遇到任何跟目录、空间、权限相关的疑难杂症我的习惯是先跑一遍df -h、df -i、ls -ld、mount四个命令把分区使用、inode、关键目录权限、挂载方式都看清楚再往下排查。目录结构的知识看似基础但它就像系统的骨架哪天你发现某个目录里的文件消失得莫名其妙或者某个软件的行为匪夷所思回头对照一下它所属目录的定位答案往往就浮出来了。
阅读完成 · 觉得有帮助?