内容


学习 Linux,101

创建和更改硬链接和符号链接

为同一文件使用多个名称

Comments

系列内容:

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

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

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

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

概述

在本文中,学习如何创建和管理硬链接和符号链接。学习:

  • 创建硬链接或软链接
  • 识别链接并了解其类型
  • 理解复制文件与链接文件之间的区别
  • 使用系统管理任务的链接

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

先决条件

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

链接简介

在存储系统上,一个文件或目录包含在一个 集合中。有关文件的信息包含在一个 inode 中,它记录的信息包括所有者、上次访问文件的时间、文件的大小、它是否是一个目录,以及可以对它进行读写操作的对象。inode 号也称为文件序列号,且在特定文件系统内是惟一的。一个目录条目 包含一个文件名或目录名,以及存储有文件或目录相关信息的 inode 的指针。

一个链接 仅仅是文件或目录的一个附加目录条目,允许同一文件或目录有两个或多个名称。一个硬链接 是指向 inode 的一个目录条目,而一个软链接符号链接 是指向提供另一目录条目名称的 inode 的一个目录条目。存储第二个名称所需的确切机制可能同时取决于文件系统和名称长度。符号链接也称为 symlinks

您可以仅为文件创建硬链接,而不管目录。例外情况是一个目录中目录本身及其父目录(. 和 ..)的特殊目录条目,它们是保持大量子目录计数的硬链接。由于硬链接指向一个 inode,且 inode 仅在特定文件系统内是惟一的,硬链接不能跨越文件系统。如果一个文件有多个硬链接,仅在指向 inode 的最后一个链接被删除且链接数为 0 时文件才会被删除。

软链接或符号链接仅根据名称(而非 inode)指向另一个文件或目录。软链接可以跨越文件系统界线。删除一个软链接不会删除目标文件或目录,且删除目标文件或目录不会自动删除任何软链接。

创建链接

首先,让我们看一下如何创建硬链接和软链接。在本文后面,我们研究如何确定和使用我们这里创建的链接。

硬链接

使用 ln 命令创建到一个现有文件(但不是目录,尽管系统将 . 和 .. 设置为硬链接)的附加硬链接。

清单 1 展示了如何创建一个包含两个文件和一个子目录的目录,其中有两个到 file1 的硬链接,其中一个在同一目录中,而另一个在子目录中。我们向 file1 添加了一个词,向 file3 添加了另一个词,并显示了子目录中链接的内容,以表明一切操作实际上都指向相同的数据。

清单 1. 创建硬链接
ian@attic4:~$ mkdir -p lpi104-6/subdir
ian@attic4:~$ touch lpi104-6/file1
ian@attic4:~$ touch lpi104-6/file2
ian@attic4:~$ ln lpi104-6/file1 lpi104-6/file3
ian@attic4:~$ ln lpi104-6/file1 lpi104-6/subdir/file3sub
ian@attic4:~$ echo "something" > lpi104-6/file1
ian@attic4:~$ echo "else" >> lpi104-6/file3
ian@attic4:~$ cat lpi104-6/subdir/file3sub
something
else

如果您试图创建跨越文件系统或用于目录的硬链接,您会得到一个错误。清单 2 显示:我的主目录和 research 目录在不同的文件系统上,跨这些目录创建硬链接的尝试失败了,而尝试创建一个到 lpi104-6 目录的硬链接也同样失败了。

清单 2. 创建硬链接失败
ian@attic4:~$ df . research
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda7             71205436   9355052  58233352  14% /
/dev/sdb3            137856204  27688208 103165264  22% /home/ian/ian-research
ian@attic4:~$ ln lpi104-6/file1 research/lpi104-6/file3
ln: creating hard link `research/lpi104-6/file3' => `lpi104-6/file1': No such file or dir
ectory
ian@attic4:~$ ln lpi104-6 lpidir104-6
ln: `lpi104-6': hard link not allowed for directory

软链接

您可以使用 ln 命令和 -s 选项创建软链接。软链接使用文件名或目录名,这些名称可能是相对或绝对的。如果使用相对名,您通常会希望将当前的工作目录作为创建链接所在的目录;否则,您创建的链接会与文件系统中的另一个点相关。清单 3 向您展示了为我们刚才创建的 file1 创建软链接的两种方法,还展示了如何创建软链接,而非清单 2 中创建失败的两个硬链接。

清单 3. 创建软链接
ian@attic4:~$ # 使用绝对路径创建符号链接
ian@attic4:~$ ln -s ~/lpi104-6/file1 ~/lpi104-6/file4
ian@attic4:~$ # 使用相对路径创建符号链接
ian@attic4:~$ cd lpi104-6/
ian@attic4:~/lpi104-6$ ln -s file1 file5
ian@attic4:~/lpi104-6$ cd ..
ian@attic4:~$ # 跨文件系统创建符号链接
ian@attic4:~$ mkdir ~ian/research/lpi104-6
ian@attic4:~$ ln -s ~/lpi104-6/file1 ~ian/research/lpi104-6/file4
ian@attic4:~$ # 为目录创建符号链接
ian@attic4:~$ ln -s lpi104-6 lpidir104-6

与之前一样,您可以使用任何链接或目标文件名来引用文件或目录。清单 4 展示了一些例子。

清单 4. 使用软链接
ian@attic4:~$ echo "another line" >> ~ian/research/lpi104-6/file
ian@attic4:~$ # cat 一个符号链接
ian@attic4:~$ cat lpi104-6/file5
something
else
another line
ian@attic4:~$ # cat 一个硬链接
ian@attic4:~$ cat lpi104-6/file1
something
else
another line
ian@attic4:~$ # 使用符号链接显示目录内容
ian@attic4:~$ ls lpidir104-6
file1  file2  file3  file4  file5  subdir

我们在创建链接时,当我们的工作目录 不是 我们希望在此建立链接的目录时,让我们使用相对路径创建一个链接。我们将在下一节研究一下这样做的原因。

清单 5. 创建一个坏的软链接
ian@attic4:~$ ln -s lpi104-6/file1 lpi104-6/file6

识别链接

在上一节中,您学习了如何创建链接,但尚不知道如何区分所创建的链接。我们现在看一下如何识别链接。

查找信息

在目前的许多系统上,ls 命令的化身是 ls --color=auto,它以不同的颜色打印不同类型的文件系统。这些颜色是可配置的。如果您使用该选项,硬链接可能会以深蓝色背景显示,符号链接带有青色文本,如图 1 所示。

图 1. 使用 Is 的 --colors 选项识别链接
使用 Is 的 --colors 选项识别链接
使用 Is 的 --colors 选项识别链接

虽然颜色可能对能区分它们的视力正常人群很方便,但对其他人用处不大,当然对 shell 脚本或程序也用处不大。没有颜色,您需要更多信息,比如使用 ls -l 命令的长清单所提供的信息。在清单 6 中,我们显式禁用了颜色输出,您还可以显式调用 /bin/ls 命令。

清单 6. 识别链接
ian@attic4:~$ ls --color=none -lR lpi104-6
lpi104-6:
total 12
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file1
-rw-r--r-- 1 ian ian    0 2010-05-26 14:11 file2
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file3
lrwxrwxrwx 1 ian ian   24 2010-05-27 17:15 file4 -> /home/ian/lpi104-6/file1
lrwxrwxrwx 1 ian ian    5 2010-05-27 17:15 file5 -> file1
lrwxrwxrwx 1 ian ian   14 2010-05-27 17:37 file6 -> lpi104-6/file1
drwxr-xr-x 2 ian ian 4096 2010-05-26 14:11 subdir

lpi104-6/subdir:
total 4
-rw-r--r-- 3 ian ian 28 2010-05-27 17:17 file3sub
ian@attic4:~$ /bin/ls -l ~ian/research/lpi104-6/file4
lrwxrwxrwx 1 ian ian 24 2010-05-25 11:51 /home/ian/research/lpi104-6/file4 -> /home/ian/
lpi104-6/file1
ian@attic4:~$ /bin/ls -l lpidir104-6
lrwxrwxrwx 1 ian ian 8 2010-05-27 17:16 lpidir104-6 -> lpi104-6

输出的第二列是一个链接数,显示到该文件的硬链接数,因此我们知道 file1、file3 和 file3sub 都有多个硬链接,指向它们代表的对象,尽管我们尚没有足够的信息确定它们都代表同一个对象。如果您删除一个链接数大于 1 的文件,inode 中的链接数将减少 1,但是文件在链接数为 0 之前不会被删除。对同一文件的其它所有硬链接将显示,目前链接数减少 1。

在输出的第一列中,您可以看到,符号链接的第一个字符是 ‘l’(小写 L)。您还可以看到 -> 字符之后显示的链接的目标。例如,file4 -> /home/ian/lpi104-6/file1。另一点是,大小是链接目标的名称中的字符数。注意,目录清单中符号链接的链接数未经更新。删除链接不会影响目标文件。符号链接不会阻止文件的删除;如果目标文件被移动或删除,符号链接会断开。为此,许多系统使用目录清单中的颜色,通常浅蓝色表示好链接,红色表示坏链接。

您可以使用 ls 命令的 -i 选项显示文件和目录条目的 inode 号。清单 7 显示我们的 lpi104-6 目录的短输出和长输出。

清单 7. 显示 inode 信息
ian@attic4:~$ ls -i lpi104-6
1680103 file1  1680103 file3  1680107 file5  1680101 subdir
1680104 file2  1680108 file4  1680110 file6
ian@attic4:~$ ls -il lpi104-6
total 12
1680103 -rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file1
1680104 -rw-r--r-- 1 ian ian    0 2010-05-26 14:11 file2
1680103 -rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file3
1680108 lrwxrwxrwx 1 ian ian   24 2010-05-27 17:15 file4 -> /home/ian/lpi104-6/file1
1680107 lrwxrwxrwx 1 ian ian    5 2010-05-27 17:15 file5 -> file1
1680110 lrwxrwxrwx 1 ian ian   14 2010-05-27 17:37 file6 -> lpi104-6/file1
1680101 drwxr-xr-x 2 ian ian 4096 2010-05-26 14:11 subdir

您还可以使用 find 命令搜索符号链接,其中使用如清单 8 所示的 -type l 查找表达式。

清单 8. 使用 find 命令定位符号链接
ian@attic4:~$ find lpi104-6 research/lpi104-6 -type l
lpi104-6/file6
lpi104-6/file5
lpi104-6/file4
research/lpi104-6/file4

断符号链接

在清单 5 中,我们创建了一个坏的软链接。这是断符号链接的一个例子。由于硬链接总是指向一个代表文件的 inode,它们总是有效的。然而,符号链接会出于多种原因而断开,包括:

  • 创建链接时链接的原始文件或目标不存在(如清单 5)。
  • 链接的目标被删除或重命名。
  • 目标路径中的一些元素被移除或重命名。

这些情况都不会报告错误,因此您需要仔细考虑一下在创建符号链接时会出现什么情况。特别地,对绝对或相对路径的选择很可能受到您对链接期内所链接对象的预期设想的影响。

如果您在使用有色输出,断符号链接可能以红色文本形式显示在一个黑色背景上,图 1 中的 file6 就属于这种情况。否则,您需要使用 ls 命令的 -H-L 选项取消引用链接并提供有关目标的信息。-H 选项取消引用命令行上的链接,而 -L 选项取消引用属于显示内容一部分的附加链接。清单 9 展示了这两种选项产生的输出的不同。

清单 9. 使用 ls -H 和 ls -L 取消引用链接
ian@attic4:~$ /bin/ls -lH lpidir104-6
total 12
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file1
-rw-r--r-- 1 ian ian    0 2010-05-26 14:11 file2
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file3
lrwxrwxrwx 1 ian ian   24 2010-05-27 17:15 file4 -> /home/ian/lpi104-6/file1
lrwxrwxrwx 1 ian ian    5 2010-05-27 17:15 file5 -> file1
lrwxrwxrwx 1 ian ian   14 2010-05-27 17:37 file6 -> lpi104-6/file1
drwxr-xr-x 2 ian ian 4096 2010-05-26 14:11 subdir
ian@attic4:~$ /bin/ls -lL lpidir104-6
/bin/ls: cannot access lpidir104-6/file6: No such file or directory
total 20
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file1
-rw-r--r-- 1 ian ian    0 2010-05-26 14:11 file2
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file3
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file4
-rw-r--r-- 3 ian ian   28 2010-05-27 17:17 file5
l????????? ? ?   ?      ?                ? file6
drwxr-xr-x 2 ian ian 4096 2010-05-26 14:11 subdir

注意,错误消息表示 file6 不存在,且其带有 '?' 字符的输出再次表示文件无法找到。

关于我们的断符号链接还有最后一点需要注意。尝试读取文件会失败,因为文件不存在。不过,如果您对目标文件有合适的权限,可以对它进行写操作,如清单 10 所示。注意,在写文件之前,我们需要创建 lpi104-6/lpi104-6。

清单 10. 对断符号链接的读写操作
ian@attic4:~$ cat lpi104-6/file6
cat: lpi104-6/file6: No such file or directory
ian@attic4:~$ echo "Testing file6" > lpi104-6/file6
bash: lpi104-6/file6: No such file or directory
ian@attic4:~$ mkdir lpi104-6/lpi104-6
ian@attic4:~$ cat lpi104-6/file6
cat: lpi104-6/file6: No such file or directory
ian@attic4:~$ echo "Testing file6" > lpi104-6/file6
ian@attic4:~$ cat lpi104-6/file6
Testing file6
ian@attic4:~$ ls lpi104-6/lpi104-6
file1

对同一文件的链接

要查出哪些文件是对特定 inode 的硬链接,您可以使用 find 命令和带文件名的 -samefile 选项或带 inode 号的 -inum 选项,如清单 11 所示。

清单 11. 找出到同一文件的硬链接
ian@attic4:~$ find lpi104-6 -samefile lpi104-6/file1
lpi104-6/subdir/file3sub
lpi104-6/file3
lpi104-6/file1
ian@attic4:~$ ls -i lpi104-6/file1
1680103 lpi104-6/file1
ian@attic4:~$ find lpi104-6 -inum 1680103
lpi104-6/subdir/file3sub
lpi104-6/file3
lpi104-6/file1

要查出哪些文件是对特定文件的符号链接,您可以使用 find 命令或带文件名的 -lname 选项,如清单 12 所示。链接可能使用一个相对或绝对路径,因此您可能希望在名称前面有星号标记,以找到所有匹配。

清单 12. 找出到一个文件或目录的符号链接
ian@attic4:~$ find lpi104-6 research/lpi104-6 -lname "*file1"
lpi104-6/file6
lpi104-6/file5
lpi104-6/file4
research/lpi104-6/file4

复制与链接之比较

根据您的不同需求,有时您要使用链接,而有时使用文件副本更好。两者的主要区别在于,链接为一个文件提供多个名称,而制作文件副本会创建两套名称不同的相同数据。您当然会使用副本作为备份,且在希望使用一个新程序而又不将操作数据置于风险中时将数据副本用作测试目的。当您需要一个文件(或目录)别名时,您使用链接,目的可能是提供一个更方便、简短的路径。在下一节中,我们将探讨链接的其他一些用处。

如您所见,当您更新一个文件时,对该文件的所有链接都会随之更新,而在复制一个文件时就不是这样。您还知道,符号链接可以断开,但随后的写操作可能会创建一个新文件。请谨慎使用链接。

链接和系统管理

链接,特别是符号链接,在 Linux 系统管理中经常用到。对命令经常使用别名,因此用户不必知道当前命令的版本号,但必要时可以通过较长的名称访问其他版本。如清单 13 中所示,gcc 命令是一个符号链接,且在我的系统上它有三个不同的名称。

清单 13. 为特定版本的命令取别名
ian@attic4:~$ which gcc
/usr/bin/gcc
ian@attic4:~$ ls -l /usr/bin/gcc
lrwxrwxrwx 1 root root 7 2009-12-28 23:17 /usr/bin/gcc -> gcc-4.4
ian@attic4:~$ find /usr/bin -lname "*gcc-4.4"
/usr/bin/x86_64-linux-gnu-gcc-4.4
/usr/bin/gcc
/usr/bin/x86_64-linux-gnu-gcc

当多个命令名使用同一底层代码时,比如停止和重启系统所用的各种命令,这时就要使用链接的其他用途。有时,像 genisofs 这样的新命令名会替代一个旧命令名,但旧名称(mkisofs)被保留作为对新命令的链接。 且备用方案设施广泛使用链接,因此您可以从诸多备用方案中为 java 等命令选择一种。清单 14 显示了一些例子。

清单 14. 命令别名示例
ian@attic4:~$ find /sbin -lname "initctl"
/sbin/restart
/sbin/start
/sbin/stop
/sbin/status
/sbin/reload
ian@attic4:~$ ls -l $(which mkisofs)
lrwxrwxrwx 1 root root 11 2009-12-28 23:17 /usr/bin/mkisofs -> genisoimage
ian@attic4:~$ ls -l $(which java)
lrwxrwxrwx 1 root root 22 2010-01-17 15:16 /usr/bin/java -> /etc/alternatives/java

库名也使用符号链接得到广泛管理,目的是让程序链接到一个通用名同时获取当前版本,或管理 64-bit 系统等能够运行 32-bit 程序的系统。一些示例如清单 15 所示。注意,有些使用绝对路径,而有些使用相对路径。

清单 15. 库链接
ian@attic4:~$ ls -l /usr/lib/libm.so
lrwxrwxrwx 1 root root 14 2010-05-27 11:23 /usr/lib/libm.so -> /lib/libm.so.6
ian@attic4:~$ find  /usr/lib/ -lname "*libstdc++*"
/usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.so
/usr/lib/libstdc++.so.6
ian@attic4:~$ ls -l /usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.so
lrwxrwxrwx 1 root root 23 2010-01-19 08:49 /usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.s
o -> ../../../libstdc++.so.6

欲了解有关链接的更多信息,请查询 ln 和本文中提到的其他命令的说明页。


相关主题


评论

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=497421
ArticleTitle=学习 Linux,101: 创建和更改硬链接和符号链接
publish-date=06212010