从 Windows 切到 Linux 的第一周,我干过一件现在想起来挺蠢的事:习惯性地想去盘符里找 C 盘、D 盘,结果打开文件管理器,看到的是一棵以/为根的目录树,满屏的/usr、/var、/etc、/dev。当时脑子里就一句话:这都什么玩意儿?
后来在嵌入式项目里被/dev下的设备节点折腾过、被/tmp的自动清理坑过、被/var/log/journal撑爆磁盘干到过线上告警——才慢慢摸清了这套目录结构背后的设计逻辑。它根本不是 Windows 那种“按存储位置分盘”的思路,而是按文件职责和生命周期去组织的。这篇文章就围绕 Linux 目录结构这个核心话题,把它掰开揉碎讲清楚:每个目录到底放什么、为什么这么放、以及真正干活的场景下这些目录会给你哪些坑。
1. 先丢掉“盘符思维”,理解 Linux 的单根目录树
1.1 为什么 Linux 没有 C 盘 D 盘
Windows 的盘符本质是一种“映射表”,把不同的物理分区或存储设备挂到C:、D:这种字母上。这种设计直观,但有个问题:目录的层级和存储设备的物理归属是强绑定的,程序如果要访问 E 盘的文件,就得写死一个盘符。
Linux 完全换了个思路:整个系统就是一棵从根/开始的单一目录树,所有存储设备、分区、网络文件系统、甚至内核数据结构,全部以挂载点的方式挂载在某一个目录节点下。你插入一个 U 盘,它默认挂到/media或/mnt下,你访问的是路径/media/usb0,而不是一个新的“F 盘”。
这也解释了为什么ls /看到的是/bin、/etc、/home这些像文件夹的东西——它们确实就是目录,只不过有些目录背后挂着一块独立的磁盘分区,有些目录本身就是系统的逻辑分类。你不需要关心/usr到底在哪个物理分区上,只需要知道:所有路径都是从根开始、按斜杠逐级展开的。
你可以在终端里输入
find / -maxdepth 1 -type d看看根目录下一共有哪些一层目录,数量不多,但每一个都承担了明确职责。
1.2 目录不是文件夹,而是“挂载点 + 功能分区”的组合
新手最容易忽略的一点:Linux 的目录层级,本质上是在回答三个问题:
- 这个文件是启动系统用的,还是运行系统用的?
- 它是系统自己生成的,还是用户手工放进去的?
- 它是真实存在于磁盘上,还是内核用内存虚拟出来的?
正是这三个问题的答案,决定了/boot、/etc、/usr、/var、/proc、/sys这些目录的划分方式。比如/boot只在启动那一刻被用到,/var里存的是日志和缓存(会有频繁写入),/proc则压根不是磁盘上的真实文件——它是内核的状态视图。
当你用df -h看到/dev/sda1挂载在/、/dev/sda2挂载在/home,就会明白:目录结构是一套逻辑组织层,物理分区是底层的存储分配层,两者之间靠挂载关系连接。这也是为什么 Linux 可以随时把一个分区重新挂载到任意空目录上,逻辑结构完全不受影响。理解这层关系,后面所有目录的“为什么”都会顺理成章。
2. 系统启动与基础运行:/boot、/etc、/usr、/var 的角色分工
这组目录是 Linux 能够启动、配置、运行的高频核心区,先说它们各自的使命,再聊实际使用中的细节。
2.1 /boot:启动时读取,平时基本不动的“冷文件区”
/boot目录放的是内核镜像(如vmlinuz-*)和初始内存盘(如initrd.img-*或initramfs-*)。Grub 引导程序在 BIOS/UEFI 初始化之后,会从这个目录读取内核,把系统拉起来。启动完成后,/boot基本就不再有读写需求了。
实际使用中容易忽略的坑:
- 新版内核装多了,
/boot会慢慢积累多个版本的vmlinuz和initramfs,而/boot所在分区往往很小(有的发行版只分了 500MB)。如果不定期清理旧内核,会出现“新的内核装不上”这种情况。清理命令是apt autoremove --purge(Debian/Ubuntu)或dnf remove $(dnf repoquery --installonly --latest-limit=-1 -q)(RHEL/Fedora)。 - 不要手贱直接删
/boot下的文件,建议通过包管理器卸载内核。手动删文件容易导致 Grub 配置和实际内核文件不匹配,重启直接进不了系统。
日常你可以用ls /boot看看自己系统里有几个内核版本,再决定要不要清理。
2.2 /etc:所有配置文件的“大本营”
/etc是静态配置文件的集中地。小到主机名(/etc/hostname)、DNS 配置(/etc/resolv.conf),大到 sshd 的配置(/etc/ssh/sshd_config)、系统服务的环境变量(/etc/environment)、仓库源(/etc/apt/sources.list),全在这里。
关键实操经验:
/etc是“全局配置目录”,它管的是这台机器本身的配置,而不是用户的个人配置。用户个人配置一般放在~/.config、~/.bashrc这种隐藏文件里。- 改任何配置文件之前先备份:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak。这不是仪式感,是真的能救命。 - 判断一个服务会不会开机启动,本质就是看
/etc/systemd/system和/lib/systemd/system里有没有对应的 unit 文件,以及它是否被 enable。 /etc/resolv.conf在现代系统上常被 systemd-resolved 或 NetworkManager 接管,手动改之后可能一重启就被覆盖。如果你真的需要固定 DNS,最佳方案是在 NetworkManager 连接配置里设置,或者直接静态配置网络接口。
想快速知道哪些配置最近被改过,可以用ls -lt /etc/按时间排序查看,这是排查系统被改动痕迹的一个高效手段。
2.3 /usr:别被名字误导,它是“用户系统资源区”不是“用户目录”
/usr这个词特别容易误会。它全称是Unix System Resources,不是 “user” 的缩写。这里面装的是系统的只读用户态程序、库、文档,通俗说就是所有用户共享的、一般不需要改动的系统软件资源。
来看具体子目录:
/usr/bin:普通用户可以直接执行的命令。/usr/sbin:管理员使用的系统管理命令(如iptables、usermod)。/usr/lib:各类软件依赖的库文件。/usr/share:架构无关的共享数据,比如图标、locale、man 手册。/usr/local:你手工编译、安装第三方软件时默认的安装前缀,比如./configure --prefix=/usr/local。
有一个关于/usr与/合并的变迁需要注意:早期/bin、/lib、/sbin是独立于/usr/bin、/usr/lib、/usr/sbin的顶层目录,因为那时候根目录所在的分区可能很小,设计者把系统启动必需的命令放在根分区上,其他软件放在/usr分区。现代发行版为了简化层级,普遍把/bin、/lib、/sbin做成指向/usr/bin、/usr/lib、/usr/sbin的软链接。所以你在ls -l /bin会看到类似/bin -> usr/bin的结果。这不是错误,是刻意为之的合并设计。
2.4 /var:跑起来之后,“变化”最剧烈的地方
/var对应英文 variable,是存放运行时可变数据的地方,它最简单粗暴的理解就是:系统运行之后会持续写入的文件全在这。
重点子目录:
/var/log:系统和应用的日志中心,故障排查第一站。像/var/log/syslog、/var/log/auth.log、/var/log/messages,背后的 journal 也默认把日志持久化到/var/log/journal下。/var/lib:发行版软件包管理器和服务的状态数据。比如 Docker 默认的数据目录/var/lib/docker,包管理器的缓存和数据库也在这里。/var/cache:各类缓存文件,可以清理。/var/tmp:跟/tmp都是临时文件,但区别在于/var/tmp在重启后保留,而/tmp在重启后通常会被清空。如果某个程序需要跨重启保存临时文件,它会倾向用/var/tmp。
老运维常调侃“日志才是生产环境的主角”,这一点在/var/log上体现得淋漓尽致。线上排查问题,第一步往往是df -h看磁盘,再du -sh /var/log/*看哪个日志文件在疯涨。这类问题后面单开一节细说。
3. 虚拟文件系统的三个大坑:/proc、/sys、/dev、/run 的“假目录”本质
有些目录你ls能看到成千上万个文件,但用du -sh一统计会发现它们占用磁盘空间近乎为零——因为它们根本不是磁盘上的真实文件,而是内核提供给你的运行时视图。理解这几个目录的“虚拟”本质,能帮你避开不少低级错误。
3.1 /proc:内核进程和运行参数的“实时快照”
/proc是一个 procfs 虚拟文件系统,挂载后里面呈现的是当前系统的进程信息与内核运行状态。你看到/proc/cpuinfo、/proc/meminfo、/proc/uptime,都不是事先写死在磁盘上的文本文件,而是你读取那一刻由内核实时生成的内容。
几个高价值用法:
cat /proc/cpuinfo:查看 CPU 型号、核心数、缓存等信息。cat /proc/meminfo:查看总内存、可用内存、缓存分布。cat /proc/[pid]/status:查看某个进程的内存、状态、父进程 ID。/proc/sys子目录(如/proc/sys/net/ipv4/ip_forward)可以用来临时修内核参数:echo 1 > /proc/sys/net/ipv4/ip_forward可以立即开启 IP 转发,但重启失效。想要持久化,得写到/etc/sysctl.conf或/etc/sysctl.d/下的配置里。
3.2 /sys:内核设备模型的“控制面板”
/sys和/proc类似,但侧重点不同。/proc偏“进程和内核全局状态”,/sys偏“硬件设备和驱动”。它导出的是内核的设备模型,让你可以通过读写文件的方式查询和修改设备属性。
实操场景:
- 查看系统所有块设备:
ls /sys/block/。 - 调整 CPU 频率调节器:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor,可以改成performance或powersave。 - 控制 LED、风扇、电池阈值等笔记本硬件参数的接口,通常也挂在
/sys/class/下。
3.3 /dev:设备文件的世界与常见误区
/dev是设备节点的所在地,Linux 的“一切皆文件”在这里体现得最明显。硬盘是/dev/sda,终端是/dev/tty*,随机数生成器是/dev/urandom。访问设备文件,本质就是对设备驱动发起操作。
新手常混淆的两个文件:
/dev/urandom和/dev/random。早期/dev/random在熵不足时会阻塞,/dev/urandom则不会,所以现代密码学加密重生成工具普遍建议用urandom。你用head -c 32 /dev/urandom | base64可以快速生成一串随机密码。/dev/null是最著名的“黑洞”:2>/dev/null就是把错误输出丢进黑洞。相反地,有个冷门文件/dev/full,向它写入会报“设备空间不足”,可以用来测试程序是否妥善处理了写满磁盘的情况。
/run也值得提一句:它是 tmpfs,内存文件系统的一种表现,存放的是系统运行时生成的 socket 文件和 pid 文件。你可能看到/run/systemd、/run/user/1000这种目录,它们每次重启都会重新生成。
注意:任何写操作直接落在这几个虚拟目录里的文件(
/proc/sys下的除外),重启后都会丢失。它不适合存任何需要持久化的数据。
4. 用户与软件的家:/home、/root、/opt、/srv、/tmp 的取舍逻辑
4.1 /home 与 /root:普通用户 vs 超级用户的家
/home下按用户名分目录,每个用户至少有一个自己的家目录。家目录里的隐藏文件就是用户的个人配置:.bashrc、.profile、.ssh、.config。
关于/home的实操建议:
- 把用户的个人数据单独分区挂载到
/home,是重装系统不丢数据的经典方案。因为重装系统只格式化/,/home挂载的分区只要不动就完好。如果你是一个会反复折腾系统的人,强烈建议这么做。 /root是 root 用户的家目录,独立于/home之外。别往/root塞普通用户的文件,也别把个人项目堆在/root下,因为 sudo 的权限模型下,root 家目录的操作痕迹通常会记录在/var/log/auth.log里,乱放文件会影响你对系统行为的判断。
4.2 /opt、/usr/local 与 /srv:第三方软件的三种归宿
很多人搞不清这几个目录的区别。我按照实际用途帮你梳理一下:
/opt:自成一体的大型第三方软件,尤其是那种“一个完整安装包解压就能跑”的软件。比如不少商业软件、IDE、以及一些打包成.tar.gz的绿色软件,通常会整体安装到/opt/<软件名>/下。/usr/local:你从源码编译安装的软件的默认安装位置。它和系统包管理器管理的/usr分开,好处是:以后如果系统自带的软件和手工编译的版本冲突,可以直接清掉/usr/local而不影响系统。/srv:存放“本机对外提供服务”的数据,比如/srv/www放了 Web 服务的站点文件、/srv/ftp放了 FTP 数据。不过实践中很多发行版默认是空的,很多开发者干脆把站点文件放/var/www,这也不算错,只是历史渊源不同。核心原则是:团队里怎么约定就怎么用,保持一致比纠结哪个“更正确”更重要。
4.3 /tmp:所有人可写,但注意粘滞位和自动清理
/tmp是系统级临时目录,所有用户都能在里面创建文件,但用户只能删除自己的文件——这就是**粘滞位(sticky bit)**在起作用。你看ls -ld /tmp会看到权限位末尾是t(drwxrwxrwt),这一位就是防止一个用户删掉另一个用户临时文件的开关。
关于/tmp的注意事项:
- 系统重启后
/tmp下的文件大概率被清空,所以不要把 MySQL 的 socket 文件、程序运行的关键状态文件放这里。 - 少量发行版把
/tmp做成了 tmpfs,也就是直接占内存。这种情况下,往/tmp里写大文件会吃内存,而不是吃磁盘。用df -h /tmp看到 Filesystem 是tmpfs就说明是这种情况。 - 临时文件比较多、占用空间大的场景,最好程序内部用
mktemp -d生成有唯一名字的临时目录,用完立刻删,避免进程崩溃后残留垃圾文件。
5. 一切随挂载而变:/mnt、/media 与自定义挂载点的正确用法
5.1 /mnt 和 /media:系统给你留的两个“接口”
/media是桌面环境自动挂载可移动设备的默认位置,U 盘、移动硬盘插上后一般自动出现在/media/<用户名>/下面。/mnt则是留给系统管理员手工挂载临时文件系统的经典位置。
日常玩法是:
- 挂载 ISO:
sudo mount -o loop ubuntu.iso /mnt/iso。 - 临时挂载 NFS 或远程目录:
sudo mount -t nfs 192.168.1.10:/data /mnt/nfs。 - 查看所有挂载点:
mount(不带参数)或findmnt输出更清晰,能直接看到树状挂载关系。
5.2 自定义挂载点的设计思路:以 /data 为例
真实生产环境里,我见过很多团队喜欢自定义一个顶层目录(比如/data)来承接业务数据,这是个好习惯。好处有两层:
- 从目录结构上把“系统数据”和“业务数据”分开,备份、迁移、故障定位都清晰。
- 后续如果数据量大了,可以把
/data迁移到独立分区或独立磁盘上,不需要改动业务路径。流程大致是:把新磁盘格式化后挂载到/mnt/newdisk,用rsync -av /data/ /mnt/newdisk/同步,再改 fstab 把新磁盘挂回/data。
反过来,不建议把业务数据直接散落在/usr/local、/opt下一大堆子目录里。因为卸载重装系统时,这些目录会跟着被格式化。把数据集中在/data这类清晰的挂载点下,才能做到“重启再多次、数据稳如山”。
5.3 磁盘不够用时的定位思路
遇到磁盘满了,第一反应别是到处猜。按这个链路走:
df -h # 整体看哪个分区满了 sudo du -xsh /root/* /home/* /opt/* /var/* /tmp/* 2>/dev/null | sort -rh | head -20-x参数很重要,它让du不跨越文件系统边界,避免你把/proc这类虚拟文件系统也统计进去,统计结果更贴合真实磁盘占用。接着逐层du -sh找到最大目录,再决定是清理还是扩容。
常见的大户集中在:/var/log/journal(systemd 日志)、/var/lib/docker(镜像和容器层)、/home/*/.cache(用户缓存)、以及/tmp下的临时文件。对 journal 我一般直接限制容量上限:
journalctl --vacuum-size=200M # 或永久限制 sudo mkdir -p /etc/systemd/journald.conf.d echo -e '[Journal]\nSystemMaxUse=200M' | sudo tee /etc/systemd/journald.conf.d/size.conf sudo systemctl restart systemd-journald6. 权限、安全与目录结构:/etc/shadow 为什么不让你看,/tmp 为什么让你写
6.1 从权限位重新理解目录
Linux 目录的权限位和执行文件的权限位行为不一样,这里有一层关键认知:目录的“执行权限”(x)其实表示“能否穿过这个目录进入子层”。所以目录的权限r--能列出文件名,但r-x才能真正走进去访问文件。这也是为什么很多目录的权限是rwxr-xr-x而不是rwxrwxrwx。
掌握七字符权限表示(如drwxr-xr-x)后,再去看目录结构:
/etc/shadow权限是-rw-r-----,只有 root 和 shadow 组能读。密码哈希集中在这里,普通用户不可读。/tmp是drwxrwxrwt,所有人都可读写执行,但粘滞位防止跨用户删除。- 用户家目录默认
drwxr-x---或drwx------,避免其他用户窥探私人文件。
6.2 安全敏感目录:/root、/etc/ssh、setuid 程序的位置
安全层面有几个固定关注点:
/etc/ssh里的私钥文件(如id_rsa、ssh_host_rsa_key)权限必须是600或640,一旦权限过宽,sshd 会直接拒绝启动或用-rwx------之类的警告提示你修复。/usr/bin有不少 setuid 程序(如/usr/bin/sudo、/usr/bin/passwd),它们允许普通用户以 root 身份执行部分受控操作。你可以用find /usr/bin -perm -4000 -ls列出,定期检查有没有异常的新增 setuid 文件,是排查系统是否被植入后门的基础动作。- root 用户不能通过 SSH 直接登录通常不是内核限制,而是
/etc/ssh/sshd_config里的PermitRootLogin选项控制。
6.3 文件系统挂载选项里的安全细节
如果系统里的人会反复插拔 U 盘,或者服务器有公网暴露面,挂载时可加noexec、nosuid、nodev选项来降低风险。
一个典型场景:把/home或/tmp设为 noexec 后,普通用户无法在这个分区里运行二进制文件(但对#!/bin/sh这类解释型脚本影响很小,因为内核直接解析脚本头执行解释器)。这能一定程度阻止用户下载“奇怪的二进制”后直接执行,但会带来一些不便。
修改/etc/fstab里的挂载选项即可,例如:
UUID=xxxx-xxxx /home ext4 defaults,noexec,nosuid 0 27. 生产环境实践:在真实机器上把目录结构用起来
7.1 一个常规服务器的合理分区布局参考
前几年我喜欢把服务器分区切成:/、/home、/var、/data分开放。/boot放 1GB 足够,/给 30-50GB,/home占一块独立空间,/var给 20GB 以上,/data按业务留足。
分区多不是目的,目的是:日志写爆不会牵连系统分区,业务数据不会和系统文件挤在一起抢空间。对小团队来说,最简单的“够用”方案是两分区:一个/,一个/data,所有业务数据、日志输出都集中到/data下面,系统盘留给系统包和用户家目录。
使用df -h和lsblk检查当前机器的分区与挂载关系,你就能快速建立起“物理设备 -> 分区 -> 挂载点 -> 业务路径”的完整链路认知。
7.2 目录结构知识在面试和排障中的真实用途
Linux 目录结构不是只有装系统那一下用得到,它会在各种场景里反复露脸:
- 排查进程为什么启动失败:先看
/var/log相关日志,然后查看/etc下的服务配置。 - 排查端口占用、命令路径问题:用
which、whereis、type确认命令到底来自/usr/bin还是/usr/local/bin,PATH顺序不同会直接影响你到底执行了哪个版本的命令。 - 自己编译软件时,
./configure --prefix=/usr/local/myapp把软件安装到独立目录下,/usr/local就变成了你手工维护的软件集合地。 - 看内核参数、调整 TCP 缓冲、设置 IP 转发,都是在
/proc/sys和/etc/sysctl.conf之间来回切换。 - 做系统加固时,把不必要的 setuid 程序去掉、收紧
/home权限、调整/tmp挂载选项,都是在目录结构和权限模型的交点上做文章。
7.3 给新手的三个“不要”
- 不要为图省事把项目文件直接放到
/root下跑,除非你确定这台机器就是你的专属玩具。 - 不要随便
chmod -R 777 /,它会把整个系统的安全边界撕得稀碎。 - 不要在网上看到 “删除某某目录可以优化系统” 就盲目执行。Linux 的目录结构本身不是“占空间大户”,真正占空间的是日志、缓存、镜像和用户数据。该清理的是垃圾,不是目录结构本身。
我在实际使用中的体会是:把这些目录当成一套“文件生命周期管理系统”来理解,比死记硬背每个目录的英文全称要有效得多。你看/boot看的是系统的冷启动阶段,/var看的是运行后的热数据,/proc和/sys看的是内核的实时状态,/home看的是人的数据边界。一旦脑子里形成这条链路,遇到任何陌生的 Linux 系统,打开终端扫一眼目录结构,基本就能判断出这台机器的定位和状态了。
最后分享一个小技巧:没事的时候跑一下cat /proc/self/mountinfo | column -t | sort,看看当前系统到底挂了哪些文件系统、谁是真正的磁盘、谁是 tmpfs、谁是 procfs。坚持看几次,你对 Linux 目录结构的理解会从“认识目录名”真正升到“理解系统运行方式”这个层面。