转载

学习 Linux,101: 查找和放置系统文件

概述

学习更多知识。开发更多项目。联系更多同行。

全新的 developerWorks Premium 会员计划提供了强大的开发工具和资源,包括 500 篇通过 Safari Books Online 提供的顶级技术文章(其中数十篇文章是专门针对 Linux 开发人员的)、最重要开发人员活动的大幅折扣、最新的 O'Reilly 大会的视频录像,等等。立即注册。

在本教程中,学习文件系统层级标准 (FHS)。学习:

  • 确定将文件放在 FHS 下的位置
  • 查找 Linux 系统上的文件和命令
  • 查找 FHS 中定义的其他重要文件和目录,并理解它们的用途

本教程可以帮助您针对 Linux Server Professional (LPIC-1) 考试 101 的主题 104 中的目标 104.7 进行应考准备。该目标的权重为 2。

组织面临着众多 Linux 发行版

考虑到有 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 类别

FHS 的核心是两种独立的文件特征:

可共享和不可共享
可共享文件可放在一个系统上并在另一个系统上使用,而不可共享文件必须位于使用它们的系统上。
静态和可变
静态文件仅通过系统管理员干预进行更改,比如安装或升级一个包,它们包括文档、库和二进制文件。可变文件是其他所有文件,比如日志、假脱机文件、数据库和用户数据,它们可由用户和系统进程更改。

这些不同之处使得具有不同的特征集的文件可以存储在不同的文件系统上。表 1是一个来自 FHS 文档的示例,展示了一种符合 FHS 的布局。

表 1. 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 路径示例。

清单 1. 一些 PATH 示例

[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 可执行文件,而不需要每次都提供一个完全限定路径。

清单 2. 更改您的路径

[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!

which、type 和 whereis 命令

在上一节中,您已知道为什么在您尝试运行 hello 命令时它可能不可用。但是,有一些其他的有用命令可帮助您确定如果键入一个命令名称,将运行哪个命令。

which 命令

可以使用 which 命令搜索您的路径,找到在您键入一个命令时将执行哪个命令(如果有)。 清单 3给出了一个在我们更新该路径之前和之后查找 hello 命令的示例。

清单 3. 使用 which

[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所示。

清单 4. 使用 which 查找多个出现位置

[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所示。

清单 5. awk 命令非常容易使用

[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 的符号链接,您可能感到很奇怪。

type 类型

有一些命令 which 命令无法找到,比如 shell 内建命令。 type 命令是一个内建命令,它告诉您如何评估一个给定命令字符串的执行情况。清单 6使用了 whichtype 来表明 type 命令不是您的路径中的可执行文件,而是一个 shell 内建命令。

清单 6. 使用 type

[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 命令

如果您想了解比程序的位置更多的信息,可以使用 whereis 命令。例如,您可以查找手册页或其他信息,如 清单 7所示。

清单 7. 使用 whereis 查找手册页

[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 所使用的固定路径。

find 命令

在本系列中早先的一篇教程 “ 学习 Linux 101:文件和目录管理 ” 中,您学习了如何根据名称(包括通配符)、路径、大小或时间戳来查找文件。在本系列中早先的另一篇教程 “ 学习 Linux 101:创建和更改硬链接和符号链接 ” 中,您学习了如何查找一个特定文件或 inode 的链接。

find 命令就像是 Linux 系统上的文件搜索工具的瑞士军刀。您可能发现有用的另外两个功能是:它可以基于用户或组名称来查找文件,或者基于权限来查找文件。

假设您想看看一个用户在 /tmp 分层结构中有哪些文件。清单 8展示了 root 用户如何查找用户 ian 在 /tmp 中的所有文件。

清单 8. 按用户和组查找文件

[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 进行测试。

清单 9. 查找不归 ian 所有的目录

[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 测试和类似 chmodumask 命令所使用的符号表达式。您可以搜索准确的权限,但更有用的做法通常是在权限表达式前添加一个连字符作为前缀,以表明您想要设置了这些权限的文件,但并不关心其他权限。清单 10演示了如何查找用户、组和每个人可执行的文件,以及查找其他用户无法读取的文件的两种不同方式。

清单 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 字节的文件。根据您安装了哪些包,您系统上的实际输出可能有所不同。

清单 11. find 的最后一个示例

[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 返回的完整路径相匹配,而且请记住正则表达式与通配符之间的区别。

locate 和 updatedb 命令

在每次运行 find 命令时,该命令都会搜索您指定的所有目录。要加快运行速度,可以使用另一个命令 locate ,它使用已存储路径信息的数据库,而不是每次都搜索文件系统。

locate 命令

locate 命令搜索通常由一个计划作业每天更新的数据库中的匹配文件。

locate 命令与路径名的任何部分匹配,而不只是与文件名匹配。将文件名放在单引号中, 包含至少一个通配符来更准确地匹配。清单 12展示了如何查找包含字符串 bin/ls 的路径,还展示了两个使用通配符来限制输出的示例。

清单 12. 使用 locate 查找路径和限制输出

[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

updatedb 命令

locate 使用的默认数据库存储在 /var 文件系统中的一个位置中,比如 /var/lib/locatedb。这个位置在使用 slocate 或 mlocate 包来提供额外的安全性或更高速度的系统上可能不同。您可以使用 locate -S 查找您的 locate 数据库上的统计数据,如 清单 13所示。

清单 13. Locatedb 统计数据

[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 配置文件来了解更多的细节。

root 文件系统中的 FHS 目录

FHS 目标是保持 root 文件系统尽可能小。但是,它必须包含引导、还原、恢复或修复系统所需的所有文件,包括经验丰富的管理员需要用于执行这些任务的实用程序。请注意,引导一个系统要求 root 文件系统上有足够的文件来允许挂载其他系统。

表 2展示了 FHS 需要的 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 分层结构

/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 上的文件放置的介绍到此结束。

原文  http://www.ibm.com/developerworks/cn/linux/l-lpic1-104-7/index.html?ca=drs-
正文到此结束
Loading...