
用了这么多年Linux不知道你有没有过这样的时刻明明系统跑得好好的突然磁盘报警你想去清点垃圾文件却不知道日志到底藏在哪个目录或者公司新来一台服务器你想装个第三方软件却纠结该丢进/usr/local还是/opt再或者你只是想改个主机名结果在/etc里翻了半天还不敢乱动。说实话这些困扰的根源就一个——没把Linux目录结构吃透。Linux目录结构不是操作系统设计者拍脑袋定的一套路径规则它背后有一套完整的逻辑哪些文件负责开机启动、哪些目录存的是静态程序、哪些位置专门放动态变化的数据、哪些“目录”其实根本不存在于硬盘上。搞清楚这套逻辑你再遇到磁盘告警、服务起不来、软件装不上、权限报错这类问题基本都能顺着目录结构快速定位到根源而不是在一堆ls输出里瞎猜。这篇内容虽然是“全解析”但我会尽量不讲那种百度百科式的干巴巴定义而是从实操角度讲清楚每个目录解决什么问题、什么时候会用到、踩过哪些坑适合刚接触Linux的新手也适合那些用了两三年但一直靠背命令混日子的朋友。1. 先建立认知框架目录结构不是随便定的1.1 一切皆文件理解Linux世界的第一个钥匙Linux的目录结构之所以“长这样”底层逻辑就一句话一切皆文件。普通文档是文件硬盘分区是文件网络连接是文件甚至CPU核数、内存占用都能以文件的形式读到。你键盘敲进去的每个字符本质上是写入了一个键盘设备文件。这套设计的妙处在于统一了操作接口。Windows里你要管理硬件得去设备管理器要读写数据得用专门的API而Linux里统统可以用打开、读取、写入、关闭这套文件操作搞定。这也解释了为什么/dev目录里能看到sda、nvme0n1这种看起来像硬件的家伙——它们确实是硬件的文件化身。也正是因为“一切皆文件”Linux的目录结构天然承担了分类所有文件资源的功能。系统启动需要哪些文件、用户数据放哪里、临时数据丢哪里、设备文件挂哪里全部通过目录划分得明明白白。你在/下看到的那些目录其实就是一个大型档案柜的标签每个标签对应一类文件。1.2 FHS标准为什么大家都按这个规矩来很多人没注意到Linux目录结构其实是有国际标准的叫FHS全称Filesystem Hierarchy Standard文件系统层次结构标准。Red Hat、Debian、Ubuntu、SUSE这些发行版虽然桌面环境和包管理器各不相同但/etc、/var、/usr这些顶层目录的含义和用途都严格遵循FHS。为什么要定这个标准想象一下你是一家软件公司的开发你要写一个安装脚本把配置放到/etc/myapp/下数据放到/var/lib/myapp/下。如果每款Linux发行版目录含义都不一样你的脚本就得针对每个系统写一份判断逻辑维护成本直接翻倍。FHS就是为了解决这种碎片化问题让软件开发者只需要对着标准写一套路径就能在几乎所有Linux系统上正常运行。FHS定义了两层结构第一层是/下各个目录的用途第二层是/usr和/var这两个关键目录下的子目录用途。标准文档本身很枯燥但它的核心思想值得记住只读和可写分离、静态和动态分离、共享和私有分离。后面我们拆解具体目录时你会反复看到这三条原则的影子。2. 第一梯队开机就要用的核心目录2.1 /bin、/sbin命令到底放在哪开机的最小流程大概是这样的主板固件引导内核内核挂载根文件系统然后启动1号进程通常是systemd或init。但这里有个鸡生蛋的问题内核要启动初始化进程得先执行它而执行就需要最基本的命令工具比如ls、cp、mount。系统还没完全起来呢这些工具从哪来答案就在/bin和/sbin。早期设计里/bin放所有用户都能用的基本命令/sbin放只有管理员才能用的系统管理命令。单用户模式、紧急修复模式下系统只会挂载根分区这时候能用的命令基本就靠这两个目录撑着。所以你会发现/bin里的东西特别“朴素”就是cat、chmod、date、echo、grep这些最基础的工具。现代发行版做了个改动很多传统上在/bin和/sbin里的文件实际被挪到了/usr/bin和/usr/sbin然后/bin和/sbin做成指向/usr/bin、/usr/sbin的软链接。这样做的目的之一是方便在系统启动早期用只读方式挂载/usr减少根文件系统被意外改动导致无法启动的风险。你在CentOS或Ubuntu上执行ls -ld /bin大概率会看到类似/bin - usr/bin的输出。实操中这个改动影响不大因为无论你敲/bin/ls还是/usr/bin/ls最终执行的都是同一个文件。但排错时有一条经验如果某天系统提示找不到某个命令别急着怀疑目录坏了先检查对应的软链接是否还正常再检查这个命令属于哪个软件包。用dpkg -S /usr/bin/lsDebian系或rpm -qf /usr/bin/lsRed Hat系就能反查命令归属。2.2 /etc系统的“控制面板”Windows用户改系统设置会去控制面板Linux里这些配置几乎都在/etc。这个目录存放的是静态的、本机的配置文件也就是说它不随程序运行而频繁变化但决定了所有程序的行为。你随便打开一台Linux服务器/etc下基本都能看到这些主角/etc/passwd、/etc/shadow用户账号和密码信息注意shadow只有root能读里面存的是密码哈希。/etc/hostname主机名配置。/etc/hosts本地主机名解析表优先级通常高于DNS。/etc/fstab文件系统挂载表定义开机自动挂载哪些分区。/etc/ssh/sshd_configSSH服务配置改端口、禁root登录都在这。/etc/resolv.confDNS服务器地址。认识/etc最大的价值在于你排查问题时第一反应应该是“看配置”而不是“重启试试”。比如某台服务器SSH连不上先看/etc/ssh/sshd_config里的Port和PermitRootLogin比如你改了主机名重启又变回去很可能是只改了/etc/hostname没同步改云平台或其他服务。改配置时有个必须养成的习惯改之前先备份。举例来说修改/etc/fstab之前先执行cp /etc/fstab /etc/fstab.bak.$(date %F)。/etc里的文件大多比较短小备份成本极低但一旦写错轻则某个服务起不来重则系统开机直接进紧急模式。我见过不止一次因为fstab里写了一个不存在的UUID导致机器重启后卡在维护模式进不去系统的情况。另外很多软件安装后会在/etc下生成默认配置你用vim手工改过之后软件升级时新配置文件经常会变成xxx.conf.rpmnew或xxx.conf.dpkg-old这类带后缀的文件。看到这种文件不要顺手删掉它说明你的手动修改和软件升级的默认配置产生了冲突需要人工对比合并。2.3 /home、/root用户的家/home是普通用户的家目录集合。每个用户登录后默认就落在/home/用户名下面桌面、文档、下载这类个人文件全在这里。用户对家目录拥有完整权限所以你在多用户服务器上部署应用时想要隔离环境最简单粗暴的方式就是每个应用建一个独立用户数据放在各自家目录里。/root是超级管理员root的家目录注意它不在/home下面这是刻意为之的。技术原因主要考虑系统进入救援模式或某些异常状态时/home所在分区可能没有挂载但/根分区必须可用/root放在/下就能保证管理员即使在紧急状态下也有可用的操作空间和配置文件。实操有个容易忽略的点家目录下的隐藏文件以.开头常常是各种程序的配置和缓存比如.bashrc是shell配置、.ssh是SSH密钥、.config是各种桌面应用的配置。当你从一台服务器迁移账号到另一台时别只拷走可见文件把整个家目录打个包带走才是完整迁移。另外清理磁盘时也要小心很多人喜欢直接删家目录下的缓存文件比如~/.cache但因为某些程序运行中可能持有这些文件的句柄删除后反而会导致内存占用不降甚至进程异常稳妥做法是用du确认后再清。3. 动态数据与静态程序 /var 和 /usr 的分工3.1 /usr不是用户目录是系统软件库新手最容易误解的目录就是/usr光看名字还以为是“user”的缩写以为是用户个人文件目录。实际上/usr是Unix System Resources的缩写在早期Unix时代它确实是用户主目录的挂载点但后来分工演化如今它存放的是系统级的应用程序和文件是所有用户共享的只读数据。/usr下面几个子目录需要重点掌握/usr/bin绝大多数用户可用命令的执行文件比如vim、python3、git。/usr/sbin管理员使用的系统管理工具比如iptables、ss。/usr/local管理员本地编译安装的软件默认安装位置。它有自己的bin、lib、etc结构相当于/usr的“用户扩展版”。/usr/share架构无关的共享数据比如文档、图标、man手册页。/usr/lib系统和应用依赖的共享库文件类似Windows里的DLL。/usr/local为什么要单独拎出来说因为它是FHS明确规定的“管理员本地软件”目录。你用yum install或apt install装的包会进/usr/bin但你自己./configure make make install编译的软件默认会装到/usr/local/bin。这样分的好处是系统包管理器和你的手动安装互不干扰卸载时也更干净。我踩过的坑是图省事直接make install把软件装进了/usr后来用包管理器升级系统组件时两个版本的库文件互相覆盖导致一堆程序起不来。从那以后凡是手动编译的我一律指定./configure --prefix/usr/local。还有个值得知道的规律/usr在理想情况下应该是只读的。很多系统的加固方案会把/usr单独分区并只读挂载防止恶意程序篡改系统二进制文件。如果你在排查入侵或者做系统完整性校验重点盯/usr/bin、/usr/sbin、/usr/lib这些目录的文件是否被改动过。3.2 /var日志、缓存和一切会变的数据如果说/usr是“静态的程序仓库”那/var就是“动态的数据大本营”。它专门存放系统运行过程中会不断增长、改写、变化的数据。最常用的几个位置/var/log系统日志目录/var/log/messages或/var/log/syslog记录系统一般日志/var/log/secure或/var/log/auth.log记录认证和安全日志Nginx、MySQL等服务的访问日志也会按各自配置写在别处但很多发行版默认放在/var/log/nginx/、/var/log/mysql/。/var/spool排队等待处理的数据比如待发送的邮件、打印任务。/var/tmp需要重启后仍然保留的临时文件和/tmp的存活时间不同后面会讲。/var/lib软件运行时的状态数据比如/var/lib/mysql是数据库文件目录/var/lib/docker是Docker的镜像和容器数据。磁盘告警时/var是最先要查的地方。因为日志文件是典型的“只增不减”型数据尤其是一些业务量大的服务器Nginx访问日志一天就能写几个GB。我处理过一台日志服务器/var/log占了整个磁盘的八成空间原因就是某个应用开启了debug级别日志且没有配置轮转。说到日志就绕不开日志轮转logrotate。Linux系统默认通过/etc/logrotate.conf和/etc/logrotate.d/下的配置按天或按大小对日志进行切割、压缩、保留。很多线上事故都是因为没有配置好logrotate的size和rotate参数。举个例子一个服务每天产生5GB日志你只保留7份那峰值空间就要留出35GB而如果配置了daily加compress日志被gzip压缩后可能只有原来的十分之一空间压力立刻缓解。排查日志占用时先看du -sh /var/log/*找出大文件再看对应服务的logrotate配置和实际轮转时间是否匹配。/var和/tmp还有一处容易混淆/var/tmp里的文件在重启后不会被系统自动清理而系统临时目录/tmp里的文件重启后大概率被清掉。如果你要放一个跨重启周期的临时数据放/var/tmp更合适。4. 虚拟文件系统的世界/proc、/sys、/dev4.1 /proc运行中的系统状态/proc可能是新手最疑惑的目录你df -h看它占用是0ls却能看到一大堆文件这些文件既不在硬盘上也不能用vim直接改多数是只读。因为/proc是一个内存中的虚拟文件系统它实时映射内核和进程的运行状态。打开任何一个进程目录/proc/pid/里面几十个文件都在描述这个进程的方方面面/proc/pid/cmdline进程启动时的完整命令行。/proc/pid/cwd进程当前工作目录。/proc/pid/environ进程的环境变量。/proc/pid/fd/进程打开的所有文件描述符这里面的软链接指向实际文件。这些信息在排查“某进程到底在跑什么”时极其有用。举个例子你感觉服务器负载异常先ps aux看进程想进一步知道这个进程的启动参数直接cat /proc/进程PID/cmdline就够了比到处找配置文件快得多。另一些顶级文件是系统资源的“只读窗口”/proc/cpuinfo能看到CPU型号和核数/proc/meminfo能看到详细内存统计/proc/loadavg能看到系统负载/proc/uptime能看到系统已运行时间。刚入门时你可以把cat /proc/meminfo的输出和free -m对比一下两者的数据完全同源理解了底层再看命令的输出就不会觉得是黑魔法。有个经典坑要提醒/proc下的文件大小显示为0是正常的因为文件内容实时生成并不存储在磁盘上。以前就有人不懂这个原理写脚本时用ls -l /proc/uptime判断文件大小结果发现永远是0导致误判正确的做法是用cat读取内容再判断。4.2 /sys内核设备树/sys和/proc类似也是虚拟文件系统但定位更聚焦它暴露的是内核的设备模型和驱动参数。/proc偏重进程和系统资源/sys则偏重硬件设备和内核模块。比如你往/sys/class/net/enp0s3/statistics/rx_bytes这个文件看一眼就能读出网卡的实时接收字节数。再比如你想临时开启某个磁盘的写入缓存可以往/sys/block/sda/queue/write_cache里写值。但注意/sys下的绝大多数控制项在重启后恢复默认这种“一次性调优”适合应急要让改动持久化得用sysctl配置或udev规则。平时操作/sys最实用的场景是调整风扇转速、查看电池状态、切换CPU调频策略这类硬件级控制。笔记本用户查电池循环次数可以直接cat /sys/class/power_supply/BAT0/cycle_count。服务器上要看磁盘转速和型号cat /sys/block/sda/device/model都能看到。/sys和/proc最需要记住的区别是/proc保存的更多是运行时刻的“快照状态”/sys更多提供的是“设备树和可调参数”。遇到硬件相关问题优先在/sys找答案遇到进程和资源问题优先在/proc找线索。4.3 /dev设备的化身/dev目录是“一切皆文件”思想最直观的体现每个硬件设备在/dev下对应一个设备文件。你不直接跟硬盘驱动打交道而是读写/dev/sda这个文件系统和驱动会负责把读写转发给真实硬件。常见的设备文件形态/dev/sda、/dev/sdbSATA/SCSI接口的磁盘整块设备。/dev/nvme0n1NVMe固态硬盘。/dev/sda1、/sda2磁盘上的分区。/dev/tty、/dev/pts/0终端设备你敲命令的窗口就是一个。/dev/null黑洞所有写入它的数据都被丢弃。/dev/zero源源不断产生零字节。搞懂设备文件对理解磁盘分区至关重要。新装系统分配磁盘时你要在/dev/vda这类整盘设备上建分区然后格式化/dev/vda1为文件系统再挂载到某个目录。整个流程的操作对象都是/dev下的设备文件而不是“盘符”这种抽象概念。排错时还有个高频场景程序崩溃后提示No space left on device但df -h看磁盘明明还有空间。这时候十有八九是磁盘的inode用完了df -i一看果然100%。因为写任何文件都需要分配一个inode元数据节点大量小文件会先把inode耗尽/dev同理。处理办法通常是删除旧的无用小文件或者调整分区时预留更多inode。5. 容易忽略的边角目录/tmp、/opt、/srv、/run5.1 /tmp临时文件的生存法则/tmp是所有程序存放临时文件的公共目录。进程运行中间产生的临时数据、安装包解压的中间产物、用户临时下载的文件都可能出现在这里。但/tmp有个重要特性它通常被系统定时清理重启后基本清空。现代systemd系统上tmpfiles.d机制配合systemd-tmpfiles服务会定期删除久未访问的文件某些发行版还有/usr/lib/tmpfiles.d/tmp.conf里配置的Age参数默认只保留10天。所以千万别把需要长期保留的东西放在/tmp否则某天突然消失你连哭的地方都没有。实操中我习惯给/tmp单独划分空间并设置合理大小。比如数据库导入导出的大文件、开发环境的构建缓存都很容易吃满/tmp一旦满了所有需要临时文件的程序都会报错症状千奇百怪但本质只有一个临时目录空间不足。用df -h /tmp和df -i /tmp一眼就能确认。5.2 /opt第三方软件的安置地FHS规定/opt用于存放**“附加应用软件包”**意思是那些不通过发行版默认包管理器安装、独立打包的第三方商业软件或大型应用。比如Oracle数据库、TeamViewer这类软件安装时经常会落到/opt/厂商/这样的结构下。/opt和/usr/local的主要区别在于/usr/local更像是“你本地手动编译安装的软件”结构遵循标准的bin、lib、share布局方便PATH统一追加/opt则更像“厂商自带打包结构”的独立安装区一个软件一个目录自包含程度高。在部署商业软件时优先扔/opt因为卸载时直接删目录就基本干净不会污染系统路径。5.3 /srv、/run、/mnt、/media各司其职/srv存放系统提供的服务数据比如网站根目录、FTP共享目录。很多发行版默认不强制使用但如果你自己部署Web服务把站点文件放/srv/www比乱放在/home下更符合规范。/run一个比较“新”的目录存放系统启动以来的运行时数据比如PID文件、socket文件、各种守护进程的状态。它本质上是早期/var/run的替代品现在/var/run通常是指向/run的软链接。注意/run的内容也是在内存中维护的 tmpfs重启就会清空services写入的pid文件没了是正常现象。/mnt临时挂载点系统管理员手动挂载外部存储时习惯上把挂载点建在这里。比如mount /dev/sdb1 /mnt/data。/media可移动设备的自动挂载目录插入U盘或移动硬盘时桌面环境会自动在/media/用户名/下创建挂载点。这些目录虽然不常直接操作但你写自动化脚本、部署服务时如果选择挂载位置遵循这些惯例能让后续维护的人少猜很多。6. 实战磁盘满了到底该查哪里6.1 从 df 到 du定位大文件理论知识说完了来点实际的。服务器告警磁盘快满了正确的排查顺序不是一上来就rm -rf而是分三步定位。第一步df -h看整体格局。重点看根分区和/var、/home是否单独分区以及各自的已用百分比。如果根分区满了而/home还有大量剩余那问题出在系统目录和/var如果/home满了重点照看用户数据。第二步du -h --max-depth1 /从根目录逐层往下扫。这一步能确定哪一级子目录占了最大空间。注意扫描大目录时可能耗时较长数据量大时可以用du -h --max-depth1 / | sort -rh | head -20直接列出最大的20个目录。第三步锁定具体目录后继续深入。比如发现/var很大就du -h --max-depth1 /var | sort -rh | head继续追到/var/log再具体到某个日志文件。核心思路是一层一层剥洋葱避免凭印象乱删。6.2 日志和缓存最常见的空间杀手排摸下来多数磁盘告警的根源集中在四类服务日志文件尤其是Nginx、Tomcat、Java应用的日志。包管理器缓存比如/var/cache/apt/archives里堆积的deb包。Docker相关/var/lib/docker下的镜像和容器层。用户家目录下的缓存和下载文件。清理时有个安全顺序先清无争议的缓存再清过期日志最后才考虑删业务数据。比如apt-get clean清掉apt缓存就是安全操作配额你确认不需要的日志用truncate -s 0 /var/log/xxx.log而不是直接rm。直接删日志文件有个坑正在写入该日志的进程仍然持有文件句柄磁盘空间不会真正释放必须重启进程或使用truncate清空内容。6.3 一次完整的排查演练假设我登录一台告警服务器操作是这样# 第一步看整体分区占用 df -h # 第二步从根目录往下扫 du -h --max-depth1 / | sort -rh | head -20 # 第三步发现 /var 很大继续追 du -h --max-depth1 /var | sort -rh | head -10 # 第四步确认是日志目录找出超过100M的文件 find /var/log -type f -size 100M -exec ls -lh {} \; # 第五步确认日志确实无价值后清空而不是删除 truncate -s 0 /var/log/某个大日志.log # 第六步再看一遍分区确认释放 df -h整个流程熟练的话两分钟就能完成。关键在于养成“先定位再动手”的习惯盲目删文件轻则误删数据重则引发更大的故障。7. 常见问题与避坑指南7.1 误删文件怎么办Linux下rm删除文件后不会进回收站这是新手最容易付出的学费。如果误删的是普通文件且文件系统支持立刻停止对该分区的写操作然后尝试用extundelete、debugfs这类工具恢复成功率取决于被删除后是否有新数据覆盖。如果是/etc下的配置文件被删很多发行版还有备用机制比如/etc的初始文件可能随系统包保留在rpm -qf对应的软件包里重新安装对应包是最快的恢复路径。最好的策略是预防。重要目录定期备份关键命令养成用rm -i或自定义alias rmrm -i的习惯脚本里删除文件前先打印日志确认目标路径。备份方案不必很复杂对于配置类文件用git维护/etc就是一个很实用的土办法。7.2 权限不足问题Linux的权限模型基于用户、用户组、其他人三类配合读、写、执行三种权限。你装完软件发现“Permission denied”先分清是文件权限还是挂载选项问题。chmod、chown能调整文件和目录的归属权限而某些外部磁盘如果以noexec选项挂载即使文件有执行权限也跑不起来这时要用mount -o remount,exec 挂载点重新挂载。/etc/sudoers是另一个高频坑你想给某个用户sudo权限直接vim改/etc/sudoers可能因为语法错误导致sudo彻底不能用。正确做法是用visudo命令编辑它会做语法检查避免你把自己锁在门外。7.3 不要乱动的目录最后说几个“手贱毁一生”的目录/boot内核和引导加载器所在目录误删内核文件直接导致无法开机。/proc、/sys虚拟文件系统乱写值可能影响运行中系统的内部状态。/dev设备文件目录删除某些设备文件后对应硬件可能变得不可用。/run运行时数据目录删掉PID文件会导致一些服务管理命令失灵。这些目录的共同特点是它们要么是系统的生命线要么是动态生成的数据。你不需要在/boot、/proc里清理垃圾文件它们的大小通常由内核和引导配置决定。碰到磁盘告警也一定从/var、/home、/tmp这些真正会产生数据的目录入手。用Linux这几年我最大的感受是目录结构不是让你背的而是让你“顺着逻辑猜的”。你知道了/etc管配置、/var管数据、/usr管程序、/proc管状态遇到任何新软件、新服务大概率都能沿着这套逻辑找到它把文件放哪了。下次再碰到服务起不来先别急着看日志文件内容先想想它应该往哪个目录写日志日志在哪配置在哪顺着目录走一遍问题往往就清楚了一半。