Unix目录结构的来历

作者:阮一峰 日期: 2012年2月 6日

Unix(包含Linux)的初学者,常常会很困惑,不明白目录结构的含义何在。

举例来说,根目录下面有一个子目录/bin,用于存放二进制程序。但是,/usr子目录下面还有/usr/bin,以及/usr/local/bin,也用于存放二进制程序;某些系统甚至还有/opt/bin。它们有何区别?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@LuffyCity ~]# tree -L 1 /  #-L 1(数字1) 表示显示/下目录的层次,1表示一层。
  /
  |-- bin     ###binary   二进制文件(命令)
  |-- boot    ###引导程序,内核镜像
  |-- dev     ###dev 设备  
  |-- etc     ###etc 系统服务配置文件
  |-- home    ###普通的家目录
  |-- lib          ###系统库 libary
  |-- lost+found
  |-- media       
  |-- misc
  |-- mnt          ###mnt 临时挂载 光驱
  |-- opt          ###opt option 可选
  |-- proc         ##process 虚拟文件系统(虚拟目录) ====>实际都是内存中的信息
  |-- root    ###root用户的家目录
  |-- sbin         ##super bin  只有root能用的命令
  |-- selinux
  |-- srv
  |-- sys          
  |-- tmp          ##垃圾堆
  |-- usr          ##存放程序
  \`-- var          ##variable 经常变   /var/log/messages  /var/log/secure

长久以来,我也感到很费解,不明白为什么这样设计。像大多数人一样,我只是根据《Unix文件系统结构标准》(Filesystem Hierarchy Standard),死记硬背不同目录的区别。

昨天,我读到了Rob Landley的简短解释,这才恍然大悟,原来Unix目录结构是历史造成的。

话说1969年,Ken ThompsonDennis Ritchie在小型机PDP-7上发明了Unix。1971年,他们将主机升级到了PDP-11。

PDP-11 当时,他们使用一种叫做RK05的储存盘,一盘的容量大约是1.5MB。

RK05

没过多久,操作系统(根目录)变得越来越大,一块盘已经装不下了。于是,他们加上了第二盘RK05,并且规定第一块盘专门放系统程序,第二块盘专门放用户自己的程序,因此挂载的目录点取名为/usr。也就是说,根目录/挂载在第一块盘,/usr目录挂载在第二块盘。除此之外,两块盘的目录结构完全相同,第一块盘的目录(/bin, /sbin, /lib, /tmp…)都在/usr目录下重新出现一次。

后来,第二块盘也满了,他们只好又加了第三盘RK05,挂载的目录点取名为/home,并且规定/usr用于存放用户的程序,/home用于存放用户的数据。

从此,这种目录结构就延续了下来。随着硬盘容量越来越大,各个目录的含义进一步得到明确。

1
2
3
4
5
6
7
  /:存放系统程序,也就是At&t开发的Unix程序。

  /usr:存放Unix系统商(比如IBM和HP)开发的程序。

  /usr/local:存放用户自己安装的程序。

  /opt:在某些系统,用于存放第三方厂商开发的程序,所以取名为option,意为"选装"。

FHS介绍

由于linux是开放源代码,各大公司和团体根据linux的核心代码做各自的操作,编程。这样就造成在根下的目录的不同。这样就造成个人不能使用他人的linux系统的PC。因为你根本不知道一些基本的配置,文件在哪里。。。这就造成了混乱。这就是FHS(Filesystem Hierarchy Standard )机构诞生的原因。该机构是linux爱好者自发的组成的一个团体,主要是是对linux做一些基本的要求,不至于是操作者换一台主机就成了linux的‘文盲’。

根据FHS(http://www.pathname.com/fhs/)的官方文件指出, 他们的主要目的是希望让使用者可以了解到已安装软件通常放置于那个目录下, 所以他们希望独立的软件开发商、操作系统制作者、以及想要维护系统的用户,都能够遵循FHS的标准。 也就是说,FHS的重点在于规范每个特定的目录下应该要放置什么样子的数据而已。 这样做好处非常多,因为Linux操作系统就能够在既有的面貌下(目录架构不变)发展出开发者想要的独特风格。

详细见 http://www.pathname.com/fhs/

FHS定义了两层规范:

  1. “/”目录下的各个目录应该放什么文件数据,例如:/etc目录下放置系统的配置文件,例如:/etc/exports,/etc/hosts,而/bin和/sbin放置程序及系统命令。

  2. 针对/usr(unix software resource|Secondary hierarchy)和/var(Variable data)这两个目录的子目录来定义。例如:/var/log下放置系统日志文件等。

提示:/var分区单独分出来,硬盘足够大。我们都有监控,剩余20%报警。

目录详细介绍

FHF要求必须要存在的目录

目录 应放置档案内容
/bin 系统有很多放置执行档的目录,但/bin比较特殊。因为/bin放置的是在单人维护模式下还能够被操作的指令。 在/bin底下的指令可以被root与一般帐号所使用,主要有:cat, chmod, chown, date, mv, mkdir, cp, bash等等常用的指令。
/boot 这个目录主要在放置开机会使用到的档案,包括Linux核心档案以及开机选单与开机所需设定档等等。 Linux kernel常用的档名为:vmlinuz,如果使用的是grub2这个开机管理程式, 则还会存在/boot/grub2/这个目录喔!
/dev 在Linux系统上,任何装置与周边设备都是以档案的型态存在于这个目录当中的。 你只要透过存取这个目录底下的某个档案,就等于存取某个装置啰~ 比要重要的档案有/dev/null, /dev/zero, /dev/tty, /dev/loop, /dev/sd等等
/etc 系统主要的设定档几乎都放置在这个目录内,例如人员的帐号密码档、 各种服务的启始档等等。一般来说,这个目录下的各档案属性是可以让一般使用者查阅的, 但是只有root有权力修改。FHS建议不要放置可执行档(binary)在这个目录中喔。比较重要的档案有: /etc/modprobe.d/, /etc/passwd, /etc/fstab, /etc/issue 等等。另外 FHS 还规范几个重要的目录最好要存在 /etc/ 目录下喔:
1. /etc/opt(必要):这个目录在放置第三方协力软体 /opt 的相关设定档
2. /etc/X11/(建议):与 X Window 有关的各种设定档都在这里,尤其是 xorg.conf 这个 X Server 的设定档。
3. /etc/sgml/(建议):与 SGML 格式有关的各项设定档
4. /etc/xml/(建议):与 XML 格式有关的各项设定档
/lib 系统的函式库非常的多,而/lib放置的则是在开机时会用到的函式库, 以及在/bin或/sbin底下的指令会呼叫的函式库而已。 什么是函式库呢?妳可以将他想成是‘外挂’,某些指令必须要有这些‘外挂’才能够顺利完成程式的执行之意。 另外 FHS 还要求底下的目录必须要存在:
- /lib/modules/:这个目录主要放置可抽换式的核心相关模组(驱动程式)喔!
/midia media是‘媒体’的英文,顾名思义,这个/media底下放置的就是可移除的装置啦! 包括软碟、光碟、DVD等等装置都暂时挂载于此。常见的档名有:/media/floppy, /media/cdrom等等。
/sbin Linux有非常多指令是用来设定系统环境的,这些指令只有root才能够利用来‘设定’系统,其他使用者最多只能用来‘查询’而已。 放在/sbin底下的为开机过程中所需要的,里面包括了开机、修复、还原系统所需要的指令。 至于某些伺服器软体程式,一般则放置到/usr/sbin/当中。至于本机自行安装的软体所产生的系统执行档(system binary), 则放置到/usr/local/sbin/当中了。常见的指令包括:fdisk, fsck, ifconfig, mkfs等等。
/srv srv可以视为‘service’的缩写,是一些网路服务启动之后,这些服务所需要取用的资料目录。 常见的服务例如WWW, FTP等等。举例来说,WWW伺服器需要的网页资料就可以放置在/srv/www/里面。 不过,系统的服务资料如果尚未要提供给网际网路任何人浏览的话,预设还是建议放置到 /var/lib 底下即可。
/tmp 这是让一般使用者或者是正在执行的程序暂时放置档案的地方。 这个目录是任何人都能够存取的,所以你需要定期的清理一下。当然,重要资料不可放置在此目录啊! 因为FHS甚至建议在开机时,应该要将/tmp下的资料都删除唷!
/usr 第二层 FHS 设定,后续介绍
/var 第二曾 FHS 设定,主要为放置变动性的资料,后续介绍

FHS建议存放的目录

目录 应放置档案内容
/home 这是系统预设的使用者家目录(home directory)。在你新增一个一般使用者帐号时, 预设的使用者家目录都会规范到这里来。比较重要的是,家目录有两种代号喔
- ~:代表目前这个使用者的家目录
- ~dmtsai :则代表 dmtsai 的家目录!
/lib\ 用来存放与 /lib 不同的格式的二进位函式库,例如支援 64 位元的
/lib64 函式库等
/root 系统管理员(root)的家目录。之所以放在这里,是因为如果进入单人维护模式而仅挂载根目录时, 该目录就能够拥有root的家目录,所以我们会希望root的家目录与根目录放置在同一个分割槽中。

第三部分:其他内容

事实上FHS针对根目录所定义的标准就仅有上面的内容,不过Linux底下还有许多目录你也需要瞭解一下的。 底下是几个在Linux当中也是非常重要的目录喔:

目录 应放置档案内容
/lost+found 这个目录是使用标准的ext2/ext3/ext4档案系统格式才会产生的一个目录,目的在于当档案系统发生错误时, 将一些遗失的片段放置到这个目录下。不过如果使用的是 xfs 档案系统的话,就不会存在这个目录了!
/proc 这个目录本身是一个‘虚拟档案系统(virtual filesystem)’喔!他放置的资料都是在记忆体当中, 例如系统核心、行程资讯(process)、周边装置的状态及网路状态等等。因为这个目录下的资料都是在记忆体当中, 所以本身不占任何硬碟空间啊!比较重要的档案例如:/proc/cpuinfo, /proc/dma, /proc/interrupts, /proc/ioports, /proc/net/* 等等。
/sys 这个目录其实跟/proc非常类似,也是一个虚拟的档案系统,主要也是记录核心与系统硬体资讯较相关的资讯。 包括目前已载入的核心模组与核心侦测到的硬体装置资讯等等。这个目录同样不占硬碟容量喔!

除了这些目录的内容之外,另外要注意的是,因为根目录与开机有关,开机过程中仅有根目录会被挂载, 其他分区则是在开机完成之后才会持续的进行挂载的行为。就是因为如此,因此根目录下与开机过程有关的目录, 就不能够与根目录放到不同的分区去。那哪些目录不可与根目录分开呢?有底下这些:

1
2
3
4
5
6
7
8
9
/etc:配置文件

/bin:重要执行档

/dev:所需要的装置文件

/lib:执行档所需的函式库与核心所需的模块

/sbin:重要的系统执行文件

这五个目录千万不可与根目录分开在不同的分区。请背下来啊。

/usr

依据FHS的基本定义,/usr里面放置的数据属于可分享的与不可变动的(shareable, static), 如果你知道如何透过网络进行分区的挂载(例如在服务器篇会谈到的NFS服务器),那么/usr确实可以分享给局域网络内的其他主机来使用喔。

/usr不是user的缩写,其实usr是Unix Software Resource的缩写, 也就是Unix操作系统软件资源所放置的目录,而不是用户的数据啦。这点要注意。 FHS建议所有软件开发者,应该将他们的数据合理的分别放置到这个目录下的次目录,而不要自行建立该软件自己独立的目录。

因为是所有系统默认的软件(distribution发布者提供的软件)都会放置到/usr底下,因此这个目录有点类似Windows 系统的C:\Windows\ + C:\Program files\这两个目录的综合体,系统刚安装完毕时,这个目录会占用最多的硬盘容量。 一般来说,/usr的次目录建议有底下这些:

/usr/文件 功能
/usr/local 这个目录一般时用来存在用户自编译安装软件的存放目录(默认)
/usr/local/bin 用户安装的小的应用程序,和一些/usr/local目录下大应用程序的符号连接
/usr/local/sbin 系统全局环境目录,可放置一些不需要加路径执行的脚本
/usr/share 系统共用的东西存在地
/usr/share/doc
/usr/share/man帮助文件
/usr/src 内核源码存放目录
/usr/bin 使用者可执行的binary file的目录(命令)
/usr/local/bin 使用者可执行的binary file的目录(命令)
/usr/lib 系统会使用到的函数库
/usr/local/lib 系统会使用到的函数库

/var

如果/usr是安装时会占用较大硬盘容量的目录,那么/var就是在系统运作后才会渐渐占用硬盘容量的目录。 因为/var目录主要针对常态性变动的文件,包括缓存(cache)、登录档(log file)以及某些软件运作所产生的文件, 包括程序文件(lock file, run file),或者例如MySQL数据库的文件等等。常见的次目录有:

/var/文件 功能
/var/log/messages 系统信息默认日志文件,非常重要,按周自动轮询
/var/log/secure 记录登录系统存取信息的文件,按周自动轮询
/var/log/wtmp 记录登录者信息的文件。last login records lastlog
/var/spool/clientmqueue sendmail临时邮件文件目录,开启邮件服务,容易使inode满。
centos6不安装,不会出现此问题

PATH含义

/bin/ls(这是绝对路径), 那你会不会觉得很奇怪:为什么我可以在任何地方执行/bin/ls这个指令呢? 为什么我在任何目录下输入 ls 就一定可以显示出一些讯息而不会说找不到该 /bin/ls 指令呢? 这是因为环境变数 PATH 的帮助。

当我们在执行一个指令的时候,举例来说ls好了,系统会依照PATH的设定去每个PATH定义的目录下搜寻档名为ls的可执行文件, 如果在PATH定义的目录中含有多个档名为ls的可执行文件,那么先搜寻到的同名指令先被执行!

现在,请下达echo $PATH来看看到底有哪些目录被定义出来了?

1
2
3
4
5
  [root@LuffyCity ~]# echo $PATH
  /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
  [root@LuffyCity ~]# su - luffy
  [luffy@manage01 ~]$ echo $PATH
  /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/luffy/.local/bin:/home/luffy/bin

PATH(一定是大写)这个变数的内容是由一堆目录所组成的,每个目录中间用冒号:来隔开,每个目录是有顺序之分的。仔细看一下上面的输出,妳可以发现到无论是root还是dmtsai都有 /bin/usr/bin 这个目录在PATH变数内,所以当然就能够在任何地方执行ls来找到/bin/ls执行档啰!因为 /binCentOS 7 当中,就是连结到 /usr/bin 去的! 所以这两个目录内容会一模一样!

我们用几个范例来让你瞭解一下,为什么PATH是那么重要的项目!

例1:如何设定默认路径

例题:

假设你是root,如果你将ls/bin/ls移动成为/root/ls(可用mv /bin/ls /root指令达成),然后你自己本身也在/root目录下, 请问:

  1. 你能不能直接输入ls来执行?
  2. 若不能,你该如何执行ls这个指令?
  3. 若要直接输入ls即可执行,又该如何进行?

答:

我们先将ls文件移动到 /root

1
[root@LuffyCity ~]# mv /bin/ls /root

接下来不论你在那个目录底下输入任何与ls相关的指令,都没有办法顺利的执行ls了! 因为PATH对应的目录下没有ls可执行文件

但是这个ls确实存在于/root底下!所以我们可以透过使用绝对路径或者是相对路径直接指定这个执行档档名, 底下的两个方法都能够执行ls这个指令:

1
2
  [root@LuffyCity ~]# /root/ls  <==直接用绝对路径指定该档名
  [root@LuffyCity ~]# ./ls      <==因为在 /root 目录下,就用./ls来指定

如果想要让root在任何目录均可执行/root底下的ls,那么就将/root加入PATH当中即可。 加入的方法很简单,就像底下这样:

1
  [root@LuffyCity ~]# PATH="${PATH}:/root"

上面这个作法就能够将/root加入到执行档搜寻路径PATH中了!如果确定这个例题进行没有问题了,请将ls搬回/bin底下,不然系统会挂掉的!

1
  [root@study ~]# mv /root/ls /bin

某些情况下,即使你已经将 ls 搬回 /bin 了,不过系统还是会告知你无法处理 /root/ls 喔!很可能是因为指令参数被快取的关系。 不要紧张,只要登出 (exit) 再登入 (su -) 就可以继续快乐的使用 ls 了!

例2: 路径的优先顺序

例题:

如果我有两个ls指令在不同的目录中,例如/usr/local/bin/ls/bin/ls那么当我下达 ls 的时候,哪个ls会被执行?

答: 那还用说,就找出 ${PATH} 里面哪个目录先被查询,则那个目录下的指令就会被先执行了!所以用 dmtsai 帐号为例,他最先搜寻的是 /usr/local/bin, 所以 /usr/local/bin/ls 会先被执行!

例3: 将当前目录加入PATH

例题:

为什么 ${PATH} 搜寻的目录不加入本目录(.)?加入本目录的搜寻不是也不错?

答:

如果在PATH中加入本目录(.)后,确实我们就能够在指令所在目录进行指令的执行了。但是由于你的工作目录并非固定(常常会使用cd来切换到不同的目录), 因此能够执行的指令会有变动(因为每个目录底下的可执行档都不相同嘛!),这对使用者来说并非好事。

另外,如果有个坏心使用者在/tmp底下做了一个指令,因为/tmp是大家都能够写入的环境,所以他当然可以这样做。 假设该指令可能会窃取使用者的一些资料,如果你使用root的身份来执行这个指令,那不是很糟糕? 如果这个指令的名称又是经常会被用到的ls时,中标的机率就更高了!

所以,为了安全起见,不建议将.加入PATH的搜寻目录中。

小结

而由上面的几个例题我们也可以知道几件事情:

  • 不同身份使用者预设的PATH不同,预设能够随意执行的指令也不同(如rootdmtsai);
  • PATH是可以修改的;
  • 使用绝对路径或相对路径直接指定某个指令的档名来执行,会比搜寻PATH来的正确;
  • 指令应该要放置到正确的目录下,执行才会比较方便;
  • 本目录(.)最好不要放到PATH当中。

参考文献