全新的 developerWorks Premium 会员计划提供了强大的开发工具和资源,包括 500 篇通过 Safari Books Online 提供的顶级技术文章(其中数十篇文章是专门针对 Linux 开发人员的)、最重要开发人员活动的大幅折扣、最新的 O'Reilly 大会的视频录像,等等。立即注册。
在本教程中,学习文件系统层级标准 (FHS)。学习:
本教程可以帮助您针对 Linux Server Professional (LPIC-1) 考试 101 的主题 104 中的目标 104.7 进行应考准备。该目标的权重为 2。
考虑到有 200 多种 Linux 发行版和多种 UNIX®变体,所有发行版都有大量共性,最好有一种在系统中放置文件的标准方法。这可以帮助新用户更好地使用新系统,帮助经验丰富的用户管理系统,并简化包分发者的任务。文件系统层级标准是一个文档,它指定了 Linux 或其他类 UNIX 系统上的通用目录布局。3.0 版于 2015 年 6 月 3 日发布,取代了 2004 年 1 月 29 日发布的 2.3 版。
本教程系列可以帮助您学习 Linux 系统管理任务。您还可以使用这些教程中的资料来对 Linux Professional Institute 的 LPIC-1:Linux 服务器专业认证考试 进行应考准备。
请参阅 “ 学习 Linux,101 :LPIC-1 学习路线图 ”,查看本系列中每部教程的描述和链接。这个路线图仍在开发中,目前反映的最新内容是在 2015 年 4 月 15 日更新的 4.0 版 LPIC-1 考试目标。一旦完成这些教程后,我们会将它们添加到路线图中。
要从本系列教程中获得最大收获,您应该拥有 Linux 的基本知识和一个正常工作的 Linux 系统,您可以在这个系统上实践本教程中涵盖的命令。除非另行说明,本教程中的示例使用了含 4.1.3 内核的 Fedora。
有时,程序的不同版本将得到不同的输出格式,所以您的结果可能并不总是与这里给出的清单和图完全相同。具体地讲,我展示的许多输出都高度依赖于我们的系统上已安装的包。您自己的输出可能非常不同,但您应该能够发现一些重要的共性。
通过在所有 Linux 发行版中都将文件放在同一个一般位置,FHS 简化了与发行版独立的软件开发。FHS 还可以用在 Linux Standard Base 中(参见)。FHS 允许用户和软件预测安装的文件和目录的位置。符合 FHS 的文件系统假设操作系统支持大多数 UNIX 文件系统中包含的基本安全功能。
FHS 的核心是两种独立的文件特征:
这些不同之处使得具有不同的特征集的文件可以存储在不同的文件系统上。表 1是一个来自 FHS 文档的示例,展示了一种符合 FHS 的布局。
可共享 | 不可共享 | |
---|---|---|
静态 | /usr/opt | /etc/boot |
可变 | /var/mail/var/spool/news | /var/run/var/lock |
Linux 系统通常包含数十万个文件。我最近安装的一个 64 位 Fedora 22 系统仅在 /usr 分层结构中就有 170,000 多个文件。
[root@atticf22 ~]# find /usr -type f | wc -l 174182
我的其他大部分安装都拥有超过 100,000 个文件,通常拥有 200,000 个或更多的文件。接下来的几节将介绍帮助您在如此浩瀚的数据海洋中查找文件(特别是程序)的工具。
如果您使用过多个 Linux 系统,您可能已经注意到,在您以 root 身份进行登录时,能够执行一些作为普通用户无法执行的命令。一些命令可由用户执行,但不能由 root 执行。当您在命令行上运行程序时,bash(或其他)shell 会在一个目录列表中搜索,以找到您请求的程序。该目录列表在 PATH 环境变量中指定。在旧版的系统上,root 用户的路径通常包含 /sbin,而非 root 用户的路径不包含它。清单 1展示了来自 3 个不同发行版的用户和 root 路径示例。
[ian@attic4-cent ~]$ # CentOS 6 [ian@attic4-cent ~]$ echo $PATH /usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/ian/bin [ian@attic4-cent ~]$ su - Password: [root@attic4-cent ~]# echo $PATH /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [ian@atticf22 ~]$ # echo Fedora 22 [ian@atticf22 ~]$ echo $PATH /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/ian/.local/bin:/home/ian/bin [ian@atticf22 ~]$ su - Password: [root@atticf22 ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [root@atticf22 ~]# ls -l /sbin lrwxrwxrwx. 1 root root 8 Aug 16 2014 /sbin -> usr/sbin ian@attic-mint17 ~ $ # Linux Mint 17.2 ian@attic-mint17 ~ $ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games ian@attic-mint17 ~ $ sudo -s attic-mint17 ~ # echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin attic-mint17 ~ # fortune Command 'fortune' is available in '/usr/games/fortune' The command could not be located because '/usr/games' is not included in the PATH environment variable. fortune: command not found
您可以看到,PATH 变量只是一组以冒号分隔的目录名称。请注意 CentOS 的用户路径和 root 路径之间的区别,以及 Linux Mint 用户路径中的两个额外的游戏目录。因为 fortune
游戏命令实际位于 /usr/games/fortune 中,所以 Mint root 用户无法玩游戏,除非他或她提供了完全限定的路径名。在用户路径中不包含 /sbin 目录的系统上, tune2fs
等程序通常只能由 root 用户找到。
通常,您的路径在一个初始化文件中设置,比如 .bash_profile 或 .bashrc。您可以通过指定新路径,针对当前 bash 进程来更改它。如果您希望新值可用于您从这个进程启动的其他进程,请记住导出 PATH 变量。假设我正在 test-hello 目录中开发一个 “Hello World” 应用程序。 清单 2展示了如何将它添加到我的路径并运行我的 hello 可执行文件,而不需要每次都提供一个完全限定路径。
[ian@atticf22 ~]$ hello bash: hello: command not found... [ian@atticf22 ~]$ test-hello/hello Hello World! [ian@atticf22 ~]$ export PATH=~/test-hello:$PATH [ian@atticf22 ~]$ hello Hello World!
在上一节中,您已知道为什么在您尝试运行 hello
命令时它可能不可用。但是,有一些其他的有用命令可帮助您确定如果键入一个命令名称,将运行哪个命令。
可以使用 which
命令搜索您的路径,找到在您键入一个命令时将执行哪个命令(如果有)。 清单 3给出了一个在我们更新该路径之前和之后查找 hello
命令的示例。
[ian@atticf22 ~]$ echo $PATH /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/ian/.local/bin:/home/ian/bin [ian@atticf22 ~]$ which hello /usr/bin/which: no hello in (/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin: /home/ian/.local/bin:/home/ian/bin) [ian@atticf22 ~]$ export PATH=~/test-hello:$PATH [ian@atticf22 ~]$ echo $PATH /home/ian/test-hello:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin: /home/ian/.local/bin:/home/ian/bin [ian@atticf22 ~]$ which hello ~/test-hello/hello
which
命令显示了一个命令在您的路径中第一次出现的位置。如果您想知道该命令是否出现了多次,可以添加 -a
选项,如 清单 4所示。
[ian@atticf22 ~]$ which awk /usr/bin/awk [ian@atticf22 ~]$ which -a awk /usr/bin/awk /bin/awk
在这里,我们在两个地方找到了 awk
命令:在 /usr/bin 中(这是系统上的命令的主要目录)和在 /bin 中(它包含系统管理员和用户都可使用,但在未挂载其他文件系统时需要的命令)。
本系列中的另一篇教程 “ 学习 Linux 101:创建和更改硬链接和符号链接 ”,介绍了如何确定这 3 个不同的文件最终都表示同一个基础 gawk
命令,如 清单 5所示。
[ian@atticf22 ~]$ ls -l $(which -a awk) lrwxrwxrwx. 1 root root 4 Jan 2 2015 /bin/awk -> gawk lrwxrwxrwx. 1 root root 4 Jan 2 2015 /usr/bin/awk -> gawk [ian@atticf22 ~]$ ls -ld /bin /usr/bin lrwxrwxrwx. 1 root root 7 Aug 16 2014 /bin -> usr/bin dr-xr-xr-x. 2 root root 69632 Aug 10 10:40 /usr/bin
在这个 Fedora 22 系统上,/bin 实际上是 /usr/bin 的符号链接,您可能感到很奇怪。
有一些命令 which
命令无法找到,比如 shell 内建命令。 type
命令是一个内建命令,它告诉您如何评估一个给定命令字符串的执行情况。清单 6使用了 which
和 type
来表明 type
命令不是您的路径中的可执行文件,而是一个 shell 内建命令。
[ian@atticf22 ~]$ which type /usr/bin/which: no type in (/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin: /home/ian/.local/bin:/home/ian/bin) [ian@atticf22 ~]$ type type type is a shell builtin
如果您想了解比程序的位置更多的信息,可以使用 whereis
命令。例如,您可以查找手册页或其他信息,如 清单 7所示。
[ian@atticf22 ~]$ whereis awk awk: /usr/bin/awk /usr/libexec/awk /usr/share/awk /usr/share/man/man1p/awk.1p.gz /usr/share/man/man1/awk.1.gz
请注意,/bin 中的 awk
部分没有被 whereis
找到。 whereis
使用的目录是固定的,所以该命令并不总是能找到您寻找的命令。 whereis
命令也可以搜索源文件,指定替代搜索路径,并搜索不常见的条目。请参阅手册页,了解如何覆盖此行为或者更改 whereis
所使用的固定路径。
在本系列中早先的一篇教程 “ 学习 Linux 101:文件和目录管理 ” 中,您学习了如何根据名称(包括通配符)、路径、大小或时间戳来查找文件。在本系列中早先的另一篇教程 “ 学习 Linux 101:创建和更改硬链接和符号链接 ” 中,您学习了如何查找一个特定文件或 inode 的链接。
find
命令就像是 Linux 系统上的文件搜索工具的瑞士军刀。您可能发现有用的另外两个功能是:它可以基于用户或组名称来查找文件,或者基于权限来查找文件。
假设您想看看一个用户在 /tmp 分层结构中有哪些文件。清单 8展示了 root 用户如何查找用户 ian 在 /tmp 中的所有文件。
[root@atticf22 ~]# find /tmp -user ian /tmp/jna-104022 ... /tmp/hsperfdata_ian /tmp/hsperfdata_ian/2390 /tmp/tracker-extract-files.1000 /tmp/.esd-1000 /tmp/.esd-1000/socket /tmp/.X11-unix/X0 /tmp/.ICE-unix/1668
您还可以使用 -group
测试来按组查找文件。您可以使用 -nouser
和 -nogroup
选项找到不属于系统上的任何用户或组的文件。与其他测试一样,您可以使用 !
对该测试求反。我通常将我的用户编号设置为 1000,因为这是许多系统上的默认设置。我还创建了一个名为 ian,组编号为 1000 的组,以防系统没有自动创建它。其他系统仍从 500 开始,或者默认情况下将新用户放在组 “users” 中。我的一些从 Red Hat 6.2 系统存档的旧研究材料仍拥有用户 500。
清单 9展示了如何查找一些不归我当前的用户组所有的目录。research/rh62/involution 归用户 500 和组 4 所有,二者都不存在于我的当前系统上。要按数字用户 id 或组 id 查找文件或目录,可以使用 -uid
或 -gid
进行测试。
[ian@atticf22 ~]$ find -L research -maxdepth 2 -type d ! -group ian research/rh62/involution research/rh62/programs research/lost+found find: ‘ research/lost+found ’ : Permission denied [ian@atticf22 ~]$ ls -ld research/rh62/involution drwxr-xr-x. 2 500 adm 4096 Nov 10 1999 research/rh62/involution
要按权限查找文件,可以使用 -perm
测试和类似 chmod
或 umask
命令所使用的符号表达式。您可以搜索准确的权限,但更有用的做法通常是在权限表达式前添加一个连字符作为前缀,以表明您想要设置了这些权限的文件,但并不关心其他权限。清单 10演示了如何查找用户、组和每个人可执行的文件,以及查找其他用户无法读取的文件的两种不同方式。
[ian@atticf22 ~]$ find . -maxdepth 1 -type f -perm -uga=x ./hello [ian@atticf22 ~]$ find . -maxdepth 1 ! -perm -o=r . ./.ssh ./.ICEauthority ./.bash_history ./.config ... ./.kde ./.cache [ian@atticf22 ~]$ find . -maxdepth 1 ! -perm -0004 . ./.ssh ./.ICEauthority ./.bash_history ./.config ... ./.kde ./.cache
我们介绍了您可以使用 find
命令执行的一些主要的搜索类型。为了进一步缩小输出范围,您可以组合多个表达式,可以向组合中添加正则表达式。要进一步了解这个多功能的命令,可以使用手册页,在您安装了信息系统时,最好使用 info find
。
清单 11展示了最后一个使用 find
搜索的示例。这个示例使用 cd
转到 /usr/include,以便可以管理清单长度,然后找到所有在其路径名中包含 packet
(无论大小写)的文件。第二个示例将此输出进一步限制到不是目录而且至少有 1500 字节的文件。根据您安装了哪些包,您系统上的实际输出可能有所不同。
[ian@atticf22 ~]$ cd /usr/include [ian@atticf22 include]$ find . -iregex ".*packet.*" ./net/if_packet.h ./linux/packet_diag.h ./linux/if_packet.h ./netpacket ./netpacket/packet.h [ian@atticf22 include]$ find . -iregex ".*packet.*" ! -type d -size +1500c ./linux/packet_diag.h ./linux/if_packet.h ./netpacket/packet.h
请注意,该正则表达式必须与 find
返回的完整路径相匹配,而且请记住正则表达式与通配符之间的区别。
在每次运行 find
命令时,该命令都会搜索您指定的所有目录。要加快运行速度,可以使用另一个命令 locate
,它使用已存储路径信息的数据库,而不是每次都搜索文件系统。
locate
命令搜索通常由一个计划作业每天更新的数据库中的匹配文件。
locate
命令与路径名的任何部分匹配,而不只是与文件名匹配。将文件名放在单引号中, 并 包含至少一个通配符来更准确地匹配。清单 12展示了如何查找包含字符串 bin/ls
的路径,还展示了两个使用通配符来限制输出的示例。
[ian@attic4-cent ~]$ # CentOS 6 [ian@attic4-cent ~]$ locate /bin/ls /bin/ls /bin/lsblk /bin/lscgroup /bin/lssubsys /usr/bin/lsattr /usr/bin/lsb_release /usr/bin/lscpu /usr/bin/lsdiff /usr/bin/lshal /usr/bin/lslogins /usr/bin/lsusb /usr/bin/lsusb.py [ian@attic4-cent ~]$ locate '//bin/ls' /bin/ls [ian@attic4-cent ~]$ locate '/bin/ls*' /bin/ls /bin/lsblk /bin/lscgroup /bin/lssubsys
locate
使用的默认数据库存储在 /var 文件系统中的一个位置中,比如 /var/lib/locatedb。这个位置在使用 slocate 或 mlocate 包来提供额外的安全性或更高速度的系统上可能不同。您可以使用 locate -S
查找您的 locate 数据库上的统计数据,如 清单 13所示。
[ian@attic4-cent ~]$ # CentOS 6 [ian@attic4-cent ~]$ locate -S Database /var/lib/mlocate/mlocate.db: 77,143 directories 776,460 files 56,872,710 bytes in file names 21,074,461 bytes used to store database
使用 updatedb
命令创建或更新该数据库。该命令通常作为计划作业每天运行。文件 /etc/updatedb.conf(或者有时候是 /etc/sysconfig/locate)是 updatedb
的配置文件。要启用每日更新,root 用户需要编辑 /etc/updatedb.conf 并设置 DAILY_UPDATE=yes。要立即创建该数据库,可以 root 身份运行 updatedb
命令。
使用 locate
的其他考虑因素包括 updatedb
数据库的每日构建的安全考虑因素和网络文件 I/O 考虑因素。请查阅手册页和 updatedb
配置文件来了解更多的细节。
FHS 目标是保持 root 文件系统尽可能小。但是,它必须包含引导、还原、恢复或修复系统所需的所有文件,包括经验丰富的管理员需要用于执行这些任务的实用程序。请注意,引导一个系统要求 root 文件系统上有足够的文件来允许挂载其他系统。
表 2展示了 FHS 需要的 root(或 /)文件系统中的目录的用途。目录或它的符号链接必须存在一个,除非它们被标记为可选(此时仅在存在相应的子系统时才需要它们)。
目录 | 用途 |
---|---|
bin | 基本的命令二进制文件 |
boot | 引导加载程序的静态文件 |
dev | 设备文件 |
etc | 特定于主机的系统配置 |
lib | 基本的共享库和内核模块 |
media | 可移动设备的挂载点 |
mnt | 临时挂载文件系统的挂载点 |
opt | 附加应用软件包 |
run | |
sbin | 基本的系统二进制文件 |
srv | 此系统提供的服务的数据 | 与运行进程相关的数据
tmp | 临时文件 |
usr | 辅助分层结构 |
var | 变量数据 |
home | 用户主目录(可选) |
lib<qual> | 替代性格式基本共享库(可选) |
root | root 用户的主目录(可选) |
/usr 和 /var 分层结构非常复杂,以至于 FHS 中有几个专门介绍它们的小节。/usr 文件系统是文件系统的第二个主要部分,包含可共享、只读的数据。它可以在系统之间共享,但目前的做法常常未这么做。
/var 文件系统包含变量数据文件,包括假脱机目录和文件、管理和日志数据,以及瞬时和临时文件。/var 的一些部分无法在不同的系统之间共享,但其他文件可以共享,比如 /var/mail、/var/cache/man、/var/cache/fonts 和 /var/spool/news。
备注:3.0 版 FHS 将 /var/run 分层结构转移到了一个单独的 /run 分层结构。/run 目录包含自系统引导以来描述它的系统信息。此目录下的文件必须在引导时删除或删节。程序可以继续使用 /var/run 实现向后兼容性,但应转而使用 /run。
要全面理解该标准,请查阅 FHS 文档(参见)。
对 Linux 上的文件放置的介绍到此结束。