内容


学习 Linux,101

查找并放置文件系统

Filesystem Hierarchy Standard 最新进展

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 学习 Linux,101

敬请期待该系列的后续内容。

此内容是该系列的一部分:学习 Linux,101

敬请期待该系列的后续内容。

概述

在本文中,学习 Filesystem Hierarchy Standard (FHS) 相关内容。学习:

  • 识别在 FHS 下何处放置文件
  • 在您的 Linux 系统上查找文件和命令
  • 查找 FHS 中定义的其他重要文件和目录并理解其用途

本文帮助您准备 Linux Professional Institute's Junior Level Administration (LPIC-1) 考试 101 中主题 104 下的目标 104.7。该目标的权值为 2。

先决条件

为了最有效地利用本系列中的文章,您应该具有基本的 Linux 知识,并需要准备一个 Linux 系统,用于练习本文介绍的命令。有时候不同版本的程序输出格式不同,因此您所得到的结果未必总是与这里所示的清单和图相同。特别是,许多输出高度依赖于系统上已经安装的包。您自己的输出可能很不一样,但是应该能够看出重要的共同点。

Filesystem Hierarchy Standard

Filesystem Hierarchy Standard 是在 Linux 或其他 UNIX® 类系统上指定目录公共布局的一个文档。通过将文件跨 Linux 发行版放置在同一个地方,FHS 简化了独立于发行版的软件开发。FHS 在 Linux Standard Base 中也有用到(参见 参考资料)。FHS 允许用户和软件预测所安装文件和目录的位置。一个遵从 FHS 的文件系统假定操作系统支持大多数 UNIX 文件系统中找到的基本安全特性。

两个独立的 FHS 类别

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

可共享 vs. 不可共享
可共享文件可以位于一个系统上,而在另一个系统上使用,而不可共享文件必须位于要使用的同一个系统上。
静态 vs. 变量
静态文件仅通过系统管理员进行变更,比如安装或更新一个包,且包含文档、库和二进制文件。变量文件是所有其他文件,比如日志、打印后台文件、数据库和用户数据,这些文件都可由用户和系统进程进行更改。

这些特征可使带不同特征集的文件存储在不同的文件系统上。表 1 是一个 FHS 文档示例,显示遵循 FHS 的一个布局。

表 1. FHS 示例
ShareableUnshareable
静态/usr
/opt
/etc
/boot
变量/var/mail
/var/spool/news
/var/run
/var/lock

文件在哪里?

Linux 系统常包含成千上万个文件。我最近安装的一个 64-bit Fedora 13 系统仅在 /usr 目录下就有 75,000 多个文件。我的大部分其他安装目录下有 100,000 多个文件,甚至 200,000 或更多文件。接下来 4 个部分将探讨可在海量数据中帮助您查找文件、特别是程序的工具。

您的 PATH 上有什么?

如果您使用过多种 Linux 系统,可能会发现,如果以根用户身份登录,就能执行 fdisk 之类的命令,如果您是一名用户,就不能执行这些命令。如果您在命令行运行程序,bash(或其他)shell 就通过一个目录列表搜索您请求的程序。目录列表是在您的 PATH 环境变量中指定的,且根用户路径可能包括 /sbin,而非根用户路径没有。清单 1 显示来自两个不同发行版的用户路径示例,以及一个根路径示例。

清单 1. 一些 PATH 示例
ian@pinguino:~$ # An Ubuntu 9.10 system
ian@pinguino:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

[ian@echidna ~]$ # An openSUSE 11.2 system
ian@attic4:~> echo $PATH
/usr/lib64/mpi/gcc/openmpi/bin:/home/ian/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/u
sr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin

[root@echidna ~]# # And as root
attic4:~ # echo $PATH
/usr/lib64/mpi/gcc/openmpi/bin:/sbin:/usr/sbin:/usr/local/sbin:/root/bin:/usr/local/bin:/
usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/usr/lib/mit/b
in:/usr/lib/mit/sbin

如您所见,PATH 变量仅是一个用冒号分隔的目录名列表。由于 fdisk 命令实际上位于 /sbin/fdisk 中,这三个路径中只有第一个和最后一个路径允许用户输入 fdisk 命令来运行,而无需提供一个完全限定名称(/sbin/fdisk)。

通常,您的路径是在 .bash_profile 或 .bashrc 等初始化文件中设置的。您可以指定一个新路径将其更改为当前 bash 进程。如果您希望新值可用于从该进程开始的其它进程,记住一定要导出 PATH 变量。如清单 2 所示。

清单 2. 更改您的 PATH
ian@attic4:~> fdisk
Absolute path to 'fdisk' is '/sbin/fdisk', so running it may require superuser privileges
 (e.g. root).
ian@attic4:~> export PATH=/sbin:$PATH
ian@attic4:~> fdisk

Usage: fdisk [-l] [-b SSZ] [-u] device
E.g.: fdisk /dev/hda  (for the first IDE disk)
  or: fdisk /dev/sdc  (for the third SCSI disk)
  or: fdisk /dev/eda  (for the first PS/2 ESDI drive)
  or: fdisk /dev/rd/c0d0  or: fdisk /dev/ida/c0d0  (for RAID devices)

which、type 和 whereis 命令

在上一节中,您了解了为什么在试图运行 fdisk 命令时该命令不可用。不过,还有几个其他有用的命令可以帮助您查出,在输入一个命令名之后真正运行的命令是哪一个。

which 命令

您可以使用 which 命令搜索您的路径,并查明在您输入一个命令时会执行哪个命令(如果有的话)。清单 3 显示了查找 fdisk 命令的一个示例。

清单 3. 使用 which 命令
ian@attic4:~> which fdisk
which: no fdisk in (/usr/lib64/mpi/gcc/openmpi/bin:/home/ian/bin:/usr/local/bin:/usr/bin:
/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/usr/lib/mit/bin:/usr/
lib/mit/sbin)
ian@attic4:~> export PATH=/sbin:$PATH
ian@attic4:~> which fdisk
/sbin/fdisk

which 命令在您的路径中显示命令的第一个搜索项。如果您希望知道是否有多个搜索项,可以添加 -a 选项,如清单 4 所示。

清单 4. 使用 which 查找多个搜索项
ian@attic4:~> which awk
/usr/bin/awk
ian@attic4:~> which -a awk
/usr/bin/awk
/bin/awk
/usr/bin/X11/awk

这里我们在三个地方找到了 awk 命令:/usr/bin(系统上命令的主目录)、/bin(包含由系统管理员和用户同时使用的命令,但只在没有其他文件系统安装时需要用到),以及 /usr/bin/X11(包含 X window 系统的二进制文件)中。

本系列的另一篇文章 “学习 Linux,101:创建和更改硬链接和符号链接”,向您展示了如何确保这三个不同的文件最终都表示同一个底层 gawk 命令,如清单 5 所示。

清单 5. Awk 命令引出 gawk
ian@attic4:~> ls -l $(which -a awk)
lrwxrwxrwx 1 root root 4 2010-02-09 00:46 /bin/awk -> gawk
lrwxrwxrwx 1 root root 8 2010-02-09 00:46 /usr/bin/awk -> /bin/awk
lrwxrwxrwx 1 root root 8 2010-02-09 00:46 /usr/bin/X11/awk -> /bin/awk

type 命令

有一些命令是 which 命令找不到的,比如 shell 内键指令。type 命令是一个内键指令,告诉您如何评估一个给定命令从而执行该命令。清单 6 使用 whichtype 表示,type 命令不是一个可在路径上找到的可执行命令,而是一个 shell 内键指令。

清单 6. 使用 type 命令
ian@attic4:~> which type
which: no type in (/usr/lib64/mpi/gcc/openmpi/bin:/home/ian/bin:/usr/local/bin:/usr/bin:/
bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/usr/lib64/jvm/jre/bin:/usr/lib/mit/bin:/usr/l
ib/mit/sbin)
ian@attic4:~> type type
type is a shell builtin

whereis 命令

如果您需要程序位置以外的更多信息,那么可以使用 whereis 命令。例如,您可以查找手册页或其他信息,如清单 7 所示。

清单 7. 使用 whereis 查找手册页
ian@attic4:~> whereis awk
awk: /bin/awk /usr/bin/awk /usr/lib64/awk /usr/bin/X11/awk /usr/share/awk 
/usr/share/man/man1/awk.1.gz /usr/share/man/man1p/awk.1p.gz

注意,使用 whereis 不能在 /sbin 中找到 awk 的副本。whereis 使用的命令是固定的,因此命令不可能总会找到您要找的东西。whereis 命令也可以搜索源文件,指定备用搜索路径,并搜索特殊条目。查询手册页,了解如何替代该行为或更改 whereis 使用的固定路径。

find 命令

在本系列的早期文章 “学习 Linux,101:文件和目录管理” 中,您了解了如何基于名称(包括通配符)、路径、大小或时间戳查找文件。在本系列的另一篇早期文章 “学习 Linux,101:创建和更改硬链接和符号链接” 中,您了解了如何查找到特定文件或索引节点的链接。

find 命令是 Linux 系统上文件搜索工具的 “瑞士军刀”。另两个您可能发现会有用的功能是,基于用户或组名查找文件的能力和基于权限查找文件的能力。

假定您希望在 /tmp 层级目录下查看用户含有的文件,清单 8 显示了根用户如何在 /tmp 中查找用户 ian 的所有文件。

清单 8. 根据用户和组查找文件
attic4:~ # find /tmp -user ian
/tmp/kde-ian
/tmp/kde-ian/closeditems
/tmp/kde-ian/closeditems/_1.66
/tmp/kde-ian/systemsettingsR27913.tmp
/tmp/.ICE-unix/2288
/tmp/orbit-ian
/tmp/orbit-ian/linc-12f7-0-33cb4ce9b1fbf
/tmp/orbit-ian/linc-7d00-0-70e5ebaa4ddac
/tmp/orbit-ian/linc-12ea-0-68260abbd2051
/tmp/orbit-ian/linc-12ea-0-3377ca55c0bd2
/tmp/ksocket-ian
/tmp/ksocket-ian/klauncherMT2183.slave-socket
...

您可以使用 -group 测试按组查找文件。而且您可以使用 -nouser-nogroup 选项查找不属于任何用户或组的文件。与其他测试一样,您可以使用 ! 对测试求反。我通常将我的用户代号设置为 1000,因为这是一些系统上的默认设置。我还创建了一个名为 ian 的组,将组号设置为 1000。其他系统仍然从 500 开始,或默认将新用户放到 ‘users’ 组中。我存档在 Red Hat 6.2 系统上的一些早期研究材料仍然有用户 500。清单 9 展示了如何查找不属于我的当前用户组的一些目录。research/rh62/involution 属于用户 500 和组 4,两者都不在我当前的系统上。要根据数值型用户 id 查找文件或目录,使用 -uid-gid 测试。

清单 9. 查找不属于 ian 的目录
ian@attic4:~> 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@attic4:~> ls -ld research/rh62/involution
drwxr-xr-x. 2 500 4 4096 1999-11-10 08:09 research/rh62/involution

要根据权限查找文件,您可以使用 -perm 测试以及符号表达式,类似于 chmodumask 命令使用的那些。您可以搜索确切的权限,但是对权限表达式加一个连字符前缀通常会更有用,因为这样可以表明您需要带这些权限集的文件,但不关心其他权限。清单 10 展示了如何查找可由用户、组和每个人执行的文件,以及查找其他人不可读取的文件的两种方法。

清单 10. 根据权限查找文件
ian@attic4:~> find . -maxdepth 1 -type f -perm -uga=x
./.xinitrc.template
ian@attic4:~> ls -l ./.xinitrc.template
-rwxr-xr-x 1 ian users 1446 2010-02-09 08:55 ./.xinitrc.template
ian@attic4:~> find . -maxdepth 1 ! -perm  -o=r
./.Xauthority
./.pulse
...
ian@attic4:~> find . -maxdepth 1 ! -perm  -0004
./.Xauthority
./.pulse
...

我们介绍了可使用 find 命令实现的几个主要搜索类型。为了进一步缩小输出范围,您可以结合多个表达式,且可以添加正则表达式。要更多地了解这个多功能命令,使用手册页,更甚者,如果您安装了信息系统,可以使用 info find 命令。

清单 11 显示了一个使用 find 的最终搜索示例。该例向 /usr/include 执行一个 cd 命令来维护清单长度的可管理性,然后查找路径名中包含 packet 的所有文件(忽略大小写)。第二个示例进一步将该输出限制为不属于目录、且大小至少为 1500 字节的文件。根据所安装的包,系统上的真实输出可能会有所不同。

清单 11. find 最终示例
ian@attic4:/usr/include> find . -iregex ".*packet.*"
./c++/4.4/java/net/DatagramPacket.h
./c++/4.4/gnu/classpath/jdwp/processor/PacketProcessor.h
./c++/4.4/gnu/classpath/jdwp/transport/JdwpPacket.h
./c++/4.4/gnu/classpath/jdwp/transport/JdwpReplyPacket.h
./c++/4.4/gnu/classpath/jdwp/transport/JdwpCommandPacket.h
./netpacket
./netpacket/packet.h
./net/if_packet.h
./linux/if_packet.h
ian@attic4:/usr/include> find . -iregex ".*packet.*" ! -type d -size +1500c
./c++/4.4/java/net/DatagramPacket.h
./c++/4.4/gnu/classpath/jdwp/transport/JdwpPacket.h
./netpacket/packet.h
./linux/if_packet.h

注意,正则表达式必须匹配 find 返回的完整路径,且要记住正则表达式和通配符之间的区别。

locate 和 updatedb 命令

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

locate 命令

locate 命令搜索一个数据库中的匹配文件,该数据库一般通过一个定时任务按日更新。

locate 命令对路径名的任意部分进行匹配,而不仅仅针对文件名。将文件名放在一个引用中 包含至少一个文件替换字符,可以实现更精确的匹配。清单 12 显示了如何查找包含 bin/ls 字符串的路径,且展示了两个使用文件替换字符来限制输出的示例。

清单 12. 使用 locate 查找路径和限制输出
ian@attic4:~> locate /bin/ls
/bin/ls
/bin/lsmod
/usr/bin/lsattr
/usr/bin/lsb_release
/usr/bin/lscpu
/usr/bin/lsdev
/usr/bin/lshal
/usr/bin/lsof
/usr/bin/lsscsi
/usr/bin/lsusb
ian@attic4:~> locate '\/bin/ls'
/bin/ls
ian@attic4:~> locate '/bin/ls*'
/bin/ls
/bin/lsmod

updatedb 命令

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

清单 13. Locatedb 统计信息
ian@attic4:~> locate -S
Database /var/lib/locatedb is in the GNU LOCATE02 format.
Locate database size: 3011297 bytes
All Filenames: 259149
File names have a cumulative length of 15751703 bytes.
Of those file names,

        11421 contain whitespace,
        0 contain newline characters,
        and 0 contain characters with the high bit set.
        Compression ratio 80.88% (higher is better)

数据库是使用 updatedb 命令予以创建和更新的。这一般作为一个定时任务按日运行。/etc/updatedb.conf 文件,或者有时是 /etc/sysconfig/locate,是 updatedb 的配置文件。为实现每日更新,根用户需要编辑 /etc/updatedb.conf 并设置 DAILY_UPDATE=yes。为立即创建数据库,以根用户身份运行 updatedb 命令。

使用 locate 的其它注意事项包括安全事项和 updatedb 用于数据库日常构建的网络文件 I/O 事项。查看手册页和 updatedb 配置文件,了解更多内容。

根文件系统中的 FHS 目录

FHS 目标是要尽量使根文件系统足够小。不过,它必须包含启动、还原、恢复或修复系统所需的所有文件,包括一个有经验的管理员执行这些任务所需的实用工具。注意,启动一个系统需要在根文件系统上有足够的空间,从而可以安装其他文件系统。

表 2 显示了 FHS 在根(或 /)文件系统下需要的目录的用途。目录或符号链接都是必需的,除了标记为可选的那些之外,这些可选项仅在相应的子系统存在时才需要。

表 2. FHS 根文件系统
目录用途
bin 必需的命令二进制文件
boot 启动加载程序的静态文件
dev 设备文件
etc 特定于主机的系统配置
lib 必需的共享库和内核模块
media 可移动媒体的装入点
mnt 临时安装文件系统的装入点
opt 附加应用程序软件包
sbin 必需的系统二进制文件
srv 本系统提供的服务用数据
tmp 临时文件
usr 二级层次结构
var 变量数据
home 用户主目录(可选)
lib<qual> 备用格式必需的共享库(可选)
root 根用户的主目录(可选)

/usr 和 /var 层次结构

/usr 和 /var 层次结构非常复杂,以至于有专门的、完整的 FHS 部分。/usr 文件系统是文件系统的第二个主要部分,包含可共享的只读数据。它可以在不同系统之间被共享,不过目前很少这么做。

/var 文件系统包含变量数据文件,包括后台打印目录和文件,管理和日志数据,以及临时文件。/var 的某些部分不可在不同的系统之间共享,但 /var/mail、/var/cache/man、/var/cache/fonts 和 /var/spool/news 等可以共享。

要完全理解标准,阅读 FHS 文档(参见 参考资料)。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=500071
ArticleTitle=学习 Linux,101: 查找并放置文件系统
publish-date=07122010