ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Linux文件目录结构全解析:从设计逻辑到运维排查实战

Linux文件目录结构全解析:从设计逻辑到运维排查实战 “Linux文件目录结构”这六个字估计劝退过不少刚接触Linux的初学者。看到一个满屏的/etc、/usr、/var第一反应往往是“这到底谁规定的怎么乱成这样”。但如果你真的在Linux环境下踩过坑、搭过服务、排查过故障就会发现这套目录结构不仅不乱反而是整个系统最精妙的设计之一。它决定了软件装在哪里、日志存在何处、配置怎么组织也决定了当你遇到“磁盘满了”“服务起不来”“库文件找不到”时该往哪个方向去排查。这篇文章不打算给你罗列一堆干巴巴的目录表格而是想从一个实际运维和开发的角度把整个Linux文件系统的设计逻辑、核心目录的用途、以及日常使用中那些容易踩的坑一次讲清楚。无论你是刚切换到Linux的开发者还是准备系统学习运维的新手这篇文章都会很有帮助。我会尽量用直白的话来解释有些地方甚至会有点啰嗦但保证都是实操中真正用得到的经验。1. 整体设计思路为什么目录要这么分1.1 一切从根开始绝对路径与挂载点的关系理解Linux目录结构首先要建立两个核心概念一个是“一切都是文件”另一个是“挂载点”。第一个概念比较好理解Linux认为设备、进程、网络接口等所有东西都可以通过文件来访问和操作。所以你在/dev下看到硬盘设备文件在/proc下看到进程信息这些都是文件只是它们不占磁盘空间。第二个概念“挂载点”是理解整套结构的钥匙。在Windows下C盘、D盘、E盘是相互独立的盘符。但Linux不是这样整个文件系统是一棵单一的树从根/开始任何一块硬盘或分区都需要挂载到这棵树的某个目录上那个目录就叫挂载点。比如你的根分区挂在/数据分区挂在/data那访问/data就相当于访问那块独立硬盘的内容。这个设计最直接的好处是用户和程序不需要关心某个目录到底在哪个物理设备上路径永远是一致的。你写一个服务配置日志路径为/var/log/app无论它落在系统盘还是独立数据盘代码都不用改。我见过不少从Windows转过来的朋友一开始最不适应的就是没有盘符概念总觉得“我的文件到底存哪了”。其实只要理解了挂载点把整个目录树想象成一棵倒置的树所有目录都是根/的分支思路就顺了。1.2 历史包袱与FHS标准Linux的目录结构并不是某个团队关起门来拍脑袋定的它继承了Unix几十年的设计传统并且在1994年以后通过FHSFilesystem Hierarchy Standard文件系统层级标准逐步固化下来。FHS规定了两件事哪些目录必须存在以及这些目录应该放什么类型的内容。正是这个标准让不同发行版的目录结构保持了惊人的一致。不管你用哪个发行版/etc一定是配置文件的家/var/log一定是日志文件的去处。这种一致性是Linux生态能繁荣发展的基础。试想一下如果每个发行版都搞一套自己的目录布局那软件包维护者、文档作者、运维脚本就全都乱套了。不过FHS给出了标准框架仍然有很多工程上的取舍和演进。最典型的是/bin、/sbin与/usr/bin、/usr/sbin的关系这里面有一段历史故事。最初Unix的系统盘很小/usr是用户目录后来随着系统工具越来越多/bin就专门放启动阶段需要的最基础命令比如ls、cp、mount而/usr/bin放普通用户常用的其他程序。现代发行版里很多发行版干脆把/bin做成了指向/usr/bin的软链接两边是同一个目录。所以你现在在CentOS或Ubuntu上执行ls -l /bin会看到它其实指向了usr/bin。这就是典型的“看上去有两套实际是一套”。1.3 文件系统层级划分的核心理念可共享与不可共享可变与不可变FHS除了规定目录还隐含了分类思想。目录可以按两个维度划分是否可共享、是否可变。可共享的意思是这个目录的内容可以放在网络上供多台机器共同使用比如/usr、/opt它们里面装的是软件理论上可以挂载到多个机器上。不可共享的是/etc、/var这类每台机器都有自己的配置和日志不能共享。可变的意思是这个目录的内容会随时变化比如/var下的日志、缓存、邮件队列一直在增长和变动。不可变的是/usr里安装的程序安装完之后通常不会自己改动。为什么要关心这个分类因为备份和磁盘规划时要重点考虑。比如你把/usr单独挂载到一个只读分区系统稳定性会大幅提升因为软件文件不会被意外篡改。把/var单独挂载到大容量磁盘日志就不会把根分区撑爆。这些都是文件系统设计哲学在实际运维中的直接应用。2. 核心目录逐层拆解谁在负责什么2.1 系统启动与用户空间/etc、/usr、/var的三角关系先看三个最重要的目录/etc、/usr、/var。把这三个搞明白Linux系统的骨架就基本掌握了。/etceditable text configuration是配置文件的集中地重要性怎么强调都不过分。系统的网络配置、用户账号密码、服务启动参数、软件许可证全部沉淀在这里。比如/etc/passwd和/etc/shadow记录用户与密码信息/etc/fstab定义开机时自动挂载的分区/etc/hosts做本机域名解析。动这些文件一定要谨慎改错了可能导致系统无法启动或服务无法正常运行。我有个习惯在改动/etc下的任何文件之前先复制一份备份比如cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak这个习惯救过我很多次。/usrUnix System Resources是系统主要软件的存放地可以把它理解为“操作系统的C盘”程序文件、库文件、头文件都在这里。/usr/bin里是普通用户可执行的程序/usr/lib里是程序运行所需的共享库/usr/include里是编译C/C程序所需的头文件/usr/share里是程序运行所需的文档、图标等资源。/varvariable存放系统运行过程中不断变化的数据。最常见的是/var/log系统日志和应用日志一般都在里面。如果磁盘满了第一件事往往是去/var/log里找找是不是某个日志文件在狂涨。此外/var/spool存放待处理的队列任务比如邮件队列、打印队列/var/tmp存放重启后仍然需要保留的临时文件。这三个目录的关系可以用一句话概括/usr是程序文件/etc是配置参数/var是运行结果。程序启动时读取配置然后把日志和状态写到/var对应位置。排查问题时想清楚这个链路基本就能快速定位方向。2.2 用户目录与多租户隔离/home、/root的边界感/home是普通用户的家目录每个用户在这里有自己的子目录用于存放个人文件和配置。用户级配置通常以隐藏文件的形式存在比如.bashrcshell配置文件、.sshSSH密钥目录、.vimrcvim编辑器配置。这些文件前面带点默认ls不显示要用ls -a才能看到。这里有一个权限隔离的细节要特别注意。举个例子假设系统里有两个用户A和BA用户的家目录权限如果设置得过宽比如755甚至777B用户就能进入A的目录查看文件这在多用户环境下会产生严重的安全隐患。所以给家目录设置合理权限非常重要最常见的是700仅所有者自己能进入。创建一个新用户时可能会发现家目录没自动生成可以手动创建并chown给用户。/root是超级管理员root用户的家目录。它独立于/home之外的原因是即使在系统进入单用户恢复模式、其他用户目录无法挂载的情况下管理员仍然能进入/root取用维护脚本和备份配置。这是运维场景中一个很实际的安全边界设计。2.3 设备与内核的虚拟窗口/dev、/proc、/sys背后的机制/dev、/proc、/sys这三个目录是理解Linux系统“虚实结合”的关键。它们都不是真实存在于磁盘上的文件而是内核动态生成的虚拟文件系统。/dev包含所有设备文件。硬盘通常是/dev/sda、/dev/sdbSATA/SAS接口NVMe硬盘是/dev/nvme0n1终端设备是/dev/tty。当你在/dev下看到一堆设备文件时记住它们并不是硬盘上存的实物而是内核提供的设备访问入口。往这些文件里写数据就是直接和设备交互。比如你要格式化一块硬盘操作对象就是/dev/sdb这个设备文件。/proc是内核和进程信息的虚拟文件系统。目录下每个数字子目录都对应一个正在运行的进程IDPID。查询CPU信息看/proc/cpuinfo内存信息看/proc/meminfo系统负载看/proc/loadavg。很多系统监控命令如ps、top本质上就是在读取/proc下的内容。除了查看信息/proc/sys目录还允许通过修改内核参数来动态调整系统行为比如开启IP转发、调整文件句柄上限。修改方法是执行sysctl -w命令或者直接往对应文件里写入值。/sys比/proc更偏向硬件设备的管理和驱动信息。它暴露了设备、驱动、总线等内核对象的结构化视图。比如查看CPU调频策略、管理电源状态、查看块设备参数都在/sys下操作。有些云平台上调优磁盘IO调度策略修改的就是/sys/block/sda/queue/scheduler这个文件。理解这三个目录你就明白为什么Linux命令里很多信息“看一眼文件就知道”因为内核把运行状态全部实时暴露成了文件。这也是“一切皆文件”思想的终极体现。2.4 应用生态的安置点/opt、/srv、/tmp、/mnt的使用边界/optoptional用于存放第三方独立软件和大型应用。很多商业软件、IDE、云平台客户端都安装在/opt下例如某些数据库、开发工具、SDK。软件的安装包、自带依赖、配置都在自己的子目录里互不干扰卸载时整目录删掉即可。/srvservice存放系统对外提供的服务数据。比如某网站的项目代码可以放在/srv/wwwGit仓库可以放在/srv/git。它并不是必须使用的目录很多运维干脆把这类数据放在/home或根分区下的自定义目录。不过按照FHS的设想/srv才是服务数据的标准位置。/tmp用于存放临时文件任何用户都可以写但需要注意两点一是里面的文件可能会在系统重启时被清理二是不要在里面存放重要数据。需要跨重启保留的临时数据应该放在/var/tmp。很多程序运行时会在这里生成临时文件占用空间大的时候也需要清理。/mnt是临时挂载目录的标准位置比如你临时插入U盘、挂载ISO镜像可以先创建/mnt/usb、/mnt/iso然后挂载上去。系统自动挂载的便携设备通常在/media和/mnt互为补充。3. 实操中的关键细节与判断方法3.1 查看目录结构tree和ls命令的进阶用法熟悉目录结构的第一步是学会高效查看。基础命令ls -l可以列出文件权限、属主、大小和时间ls -la多了隐藏文件。但展示目录树时ls就力不从心了这时可以用tree命令。tree默认可能没有安装Ubuntu/Debian下执行apt install treeCentOS/RHEL下执行yum install tree。装上之后查看/usr的完整结构可以tree -L 2 /usr-L参数控制层级深度避免输出过深导致刷屏。只看目录不看文件可以加-d比如tree -d -L 1 /etc可以一屏看完整目录布局。另外不要轻视df -h和du -sh这两个命令。df -h查看磁盘分区的空间使用情况能直接看到哪个挂载点快满了du -sh 目录名查看某个目录占用的总大小。它们和目录配合使用排查空间问题非常高效。3.2 判断目录是否独立分区挂载点查询与空间占用分析很多时候需要知道某个目录是不是独立分区。最简单的办法是执行df -h /目录路径系统会告诉你这个路径所在的文件系统。比如df -h /var/log和df -h /输出一致说明日志并没有独立分区如果输出不同的设备说明/var/log有独立挂载。更全局的视角用mount命令或查看/proc/mounts这个文件显示了当前系统所有挂载点、设备、文件系统类型和挂载参数。我排查问题时第一件事就是cat /proc/mounts看哪个目录挂载了哪些设备。du --max-depth1 -h /某个目录能一层层定位哪个子目录占用空间最大。实际操作时从根目录开始逐层往下追踪比如先看/var多大再看/var/log再看/var/log/nginx花不了多少时间就能锁定罪魁祸首。3.3 为什么要避免随意创建顶层目录在日常使用中经常有人为了方便直接在根目录下创建/test、/tools、/backup这类自定义顶层目录。从功能上讲这当然不违法系统不会因此出错但我不建议这么做。原因有三点一是污染根目录让目录结构变得混乱不熟悉这套布局的人容易误判二是备份策略往往基于标准目录设计自定义顶层目录很容易被排除在备份范围之外三是如果以后团队协作或交接标准目录体系的统一性会大大降低沟通成本。如果确实需要自定义数据目录建议在挂载点下创建或者使用/srv、/opt、/data这类约定俗成的位置。在运维实践中规范的第一步就是别乱造顶层目录。3.4 符号链接与硬链接目录结构中容易被忽略的细节在查看目录时经常看到某些目录是指向其他位置的符号链接。比如刚才提到的/bin指向/usr/bin/lib指向/usr/lib。要区分符号链接和真实目录执行ls -l查看第一列开头的字母l开头就是链接d开头就是真实目录。符号链接之所以存在的最大价值是兼容很多旧脚本和程序写死了/bin/ls这种路径而新发行版把可执行文件挪到了/usr/bin于是做一个/bin到/usr/bin的软链接两边都能访问。理解这一点后你看到/lib - usr/lib这类输出就不会再困惑了。硬链接在目录结构中用得较少它不能指向目录只能指向同一文件系统内的文件。但有一点要特别注意硬链接没有独立的“删除”概念只有所有链接都被移除后文件才会真正释放空间。在日常操作中如果你是用ln创建硬链接修改任何一个名字下的文件内容其他名字下的内容也会同步改变它们本质上是同一个文件的多个名字。4. 常见问题与排查技巧实录4.1 磁盘满但找不到大文件inode耗尽与隐藏文件陷阱这是运维中非常经典的一个谜题用df -h一看根分区100%但执行du -sh /却显示只用了一半文件到底藏在哪里答案往往是两个原因。第一个原因是某个进程已经删除但仍然被占用的文件。一个文件被进程打开后即使你rm删除了它只要进程没关闭磁盘空间并不会真正释放。排查方法是用lsof | grep deleted找出这些进程重启它们或者让它们重新加载空间才能释放。第二原因是/proc、/sys这一类的虚拟文件系统占了空间但du默认不会去统计它们它们是0字节不过df会单独显示它们的挂载点占用。还有一种情况是inode耗尽。df -h显示空间还有剩余但系统却报“No space left on device”这是因为小文件太多把inode表占满了。用df -i查看inode使用率一旦达到100%即使还有剩余空间也无法创建新文件。这种情况常见于邮件队列、临时文件目录或其他产生海量小文件的服务。排查时可以先find / -xdev -type f | wc -l统计文件总数再用for dir in /var/spool /tmp; do echo $dir: $(find $dir -type f | wc -l); done一类的方法定位是哪个目录文件数量异常。4.2 误删除/关键文件后系统异常从启动流程理解修复路径新手最怕的事情之一是不小心删了关键文件比如误删/etc/passwd、/lib64/libc.so.6这类核心库。遇到这种情况不要慌先判断你能拿到什么环境。如果你还停留在系统内多数是能补救的如果系统直接起不来就需要进入单用户模式或者用Live CD启动。举个例子误删了/etc/passwd但你有备份前面说的备份习惯派上用场了直接恢复即可。如果没有备份而系统里还存在/etc/passwd-这个自动备份文件可以cp /etc/passwd- /etc/passwd恢复。如果连这个文件也没有麻烦一些需要进入救援环境手工重建但这意味着所有用户的ID映射都要重新构建。实际工作中最常遇到的其实不是删除整个文件而是把/etc/nginx/nginx.conf这类配置文件改错了。这种场景的恢复思路是先用备份文件恢复再逐步对比找出错误的配置项。我之前就遇到过改错配置导致服务无法启动的情况最后的排查过程是启动服务看报错系统很明确地指出在哪一行有问题再对照备份修正即可。4.3 目录权限导致的服务无法访问权限排查三件套运行某个服务时提示“Permission denied”但文件明明存在这个问题的根源大多是权限或SELinux限制。通常排查分三步。第一步查看文件的属主和权限执行ls -l 文件名看用户是否对该文件有读写执行权限。第二步检查目录权限文件能读但目录没有执行权限同样无法进入。在Linux中目录的x权限决定你是否能进入目录r权限只决定你是否能列出目录内容这是个非常容易弄混的细节。第三步查看SELinux上下文执行ls -Z看文件的SELinux标签如果标签不对执行restorecon -v 文件名恢复默认标签通常就能解决问题。这“三件套”在大部分权限访问问题中都能覆盖。如果都排查完还没解决再考虑ACL访问控制列表算法上还有更复杂的规则但对日常运维来说这三步已经足够应对绝大多数场景了。4.4 服务日志为何找不到日志轮转与日志目录符号链接有些服务配置了日志路径但在标准日志目录里怎么也找不到对应文件。常见原因是某些服务尤其是一些Java应用默认把日志写到了应用自己的目录下没走系统日志体系。找出真实位置的方式是在/etc下查应用配置比如grep -r log /etc/应用目录/或者用lsof -p 应用PID | grep log直接看进程打开的日志文件。另一个容易困扰人的点是/var/log下某些文件其实是符号链接比如vim /var/log/syslog看起来是文件实际上也可能跳转到别处。这不影响使用但你要是用du统计日志大小可能会惊讶于链接指向的空间占用。日志轮转是另一个大话题logrotate服务会定期切割、压缩、清理日志避免单个文件无限膨胀。默认配置通常放在/etc/logrotate.conf和/etc/logrotate.d/目录下如果你的应用日志不轮转建议在/etc/logrotate.d/下创建一个配置文件把路径、保留份数、触发条件都写清楚否则半个月后磁盘就会教你怎么做人。5. 工具链与习惯养成让目录结构成为直觉5.1 常用命令速查不用记路径也能快速定位日常操作中与其死记路径不如掌握几个自动定位的命令。which 命令名能告诉你可执行文件在哪里比如which nginx输出/usr/sbin/nginx。type 命令名能显示命令类型是内置命令、外部命令还是别名。find / -name 文件名 2/dev/null能在全盘搜索文件但默认会输出大量权限错误加上2/dev/null可以过滤掉错误信息。更精准的搜索用locate 文件名它依赖一个定期更新的数据库速度极快缺点是刚创建的文件可能不在索引里需要先执行updatedb更新。查看软件包安装的文件列表用包管理器非常方便Ubuntu/Debian用dpkg -L 包名CentOS/RHEL用rpm -ql 包名。想知道某个文件属于哪个软件包Debian系用dpkg -S 文件名RedHat系用rpm -qf 文件名。这些命令比手动翻find高效得多。5.2 制定自己的目录使用规范给团队立规矩的好处无论是个人服务器还是团队协作我都建议形成一份简单的目录使用约定。比如约定系统服务配置改到/etc/应用名/应用数据统一放到/var/lib/应用名/日志放到/var/log/应用名/临时部署脚本放入/opt/scripts/备份文件放到/backup/。不要嫌这些约定死板一旦形成习惯维护的成本会大幅降低。我曾经接手过一台服务器前人把脚本放在/root/scripts/数据库备份放在/home/backup/网站代码放在/www/日志分散在各应用目录里。结果每次排查问题都要到处翻极费时间。后来花了一个周末把所有东西按规范归类之后处理问题速度快了不止一个量级。这真的不是洁癖问题而是实打实的效率问题。5.3 备份策略中的目录优先级排序了解了目录结构的意义后备份策略也变得清晰。需要备份的内容优先级从高到低是/etc系统配置、/home用户数据、/var/lib应用数据库与状态、/srv或自定义数据目录服务数据、/opt第三方软件配置。/usr、/bin、/lib这些系统安装目录通常不需要备份因为重新安装系统后可以通过包管理器恢复。执行备份时核心是保留目录的属主、权限和链接。用tar做备份时强烈建议加-p参数保留权限属性还原的时候加-p参数恢复。如果一个备份包解压之后所有文件都变成当前用户的属主那恢复出来的服务一定会以诡异的方式报错这是很多备份还原后系统异常的根源。5.4 深入学习的方向与路径如果想要继续深入理解Linux文件系统我建议按这个顺序走先阅读man hier系统目录结构的官方说明文档很多发行版都有这个手册页它简要说明了每个目录的用途。然后结合FHS标准文档理解分类哲学再看文件系统实现层面的概念比如inode、超级块、硬链接计数。磁盘相关的知识也不能落下了解lsblk、fdisk、mkfs是怎么管理块设备和创建文件系统的。到了更高阶的阶段就可以接触LVM逻辑卷管理、btrfs、XFS这些高级文件系统的特性了比如快照、扩容、去重。这些高级特性都建立在基础目录结构之上学好目录结构等于打好了整个Linux知识体系的地基。6. 致新手和老手的一句话目录结构这个东西刚开始学的时候觉得它琐碎、难记但我个人实际使用下来的体会是它其实是Linux设计思想最好的载体。每当你搞清楚一个目录为什么存在系统设计者当时的取舍逻辑也就跟着浮出水面了。所以不用刻意去背多用、多看、多踩坑那些目录自然就长在记忆力里了。最后再分享一个小技巧如果你在一个陌生系统上完全不知道某个目录是干嘛的先去查资料确认再操作。我最开始时曾在/usr里乱删文件以为能释放空间结果系统半残。从那以后我养成一个好习惯——在做任何目录批量操作之前先执行ls -ld看看这个目录的属主和权限再执行du -sh看看它的大小最后确认这是不是软链接到系统关键位置的“替身”。确认清楚了再动手Linux会给你极大的自由度但也会为每一次鲁莽操作买单确保不出问题的最好方式就是保持对目录结构的敬畏。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进