Contents

Linux命令–查找损坏的符号链接

1. 概述

在本教程中,我们将了解如何使用不同形式的find 命令查找损坏的符号链接。

2.符号链接

符号链接、符号链接甚至软链接都是指向其他链接、文件、目录和资源的文件。它们类似于 Windows 中的快捷方式。

由于它们是链接,一旦目标不再可用,它们就变得毫无用处。

我们的示例将在以下目录结构中运行:

/uploads/find_broken_symlinks/1.png

要重现上述环境,我们可以在空目录中运行这些命令:

mkdir -p blogdemo/dir-1/dir-2/dir-3/
touch blogdemo/file.txt
touch blogdemo/dir-1/file-1.txt
touch blogdemo/dir-1/dir-2/file-2.txt
touch blogdemo/dir-1/dir-2/dir-3/file-3.txt
ln -s dir-2/dir-3/ blogdemo/dir-1/dir-3
ln -s ../../file-1.txt blogdemo/dir-1/dir-2/dir-3/file-1.txt
ln -s blogdemo/nonexistent-directory blogdemo/dir-1/dir-2/link-to-nonexistent-directory
ln -s dir-4/file-4.txt blogdemo/dir-1/dir-2/dir-3/file-4.txt
ln -s dir-2/file-2.txt blogdemo/dir-1/file-2.txt
ln -s ../filex.txt blogdemo/dir-1/filex.txt
ln -s ../cyclic-link blogdemo/dir-1/cyclic-link
ln -s dir-1/cyclic-link blogdemo/cyclic-link
ln -s . blogdemo/infinite-loop

3. 查找损坏的符号链接

find命令的结构如下:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [starting-point...] [expression]

** -H-L和*-P选项控制符号链接的处理方式,当省略时,使用-P*作为默认值**。

当使用*-Pfind*检查或打印来自符号链接的信息时,详细信息来自符号链接本身的属性。

我们将为我们的命令假设一个 Bash shell。

3.1. 简单的方法

检测损坏的符号链接的最简单方法是使用以下命令:

find blogdemo -xtype l

在我们的环境中执行上述命令将产生以下输出:

find: ‘blogdemo/cyclic-link’: Too many levels of symbolic links
find: ‘blogdemo/dir-1/cyclic-link’: Too many levels of symbolic links
blogdemo/dir-1/filex.txt
blogdemo/dir-1/dir-2/link-to-nonexistent-directory
blogdemo/dir-1/dir-2/dir-3/file-4.txt

**在前两行中,我们可以看到不仅检测到损坏的符号链接,而且还报告循环链接。**在循环链接之后,我们看到了断开的链接。

我们使用了*-xtype l参数,该参数仅适用*于损坏的符号链接

我们可以通过包含*-P*标志来实现相同的目标:

find blogdemo -P -xtype l

正如我们可能猜到的,这意味着-P 是默认值。

3.2. 便携方式

对于 POSIX 兼容的 shell,我们可以使用下面的解决方案,因为-xtype*可能并非在所有系统上都可用*:

find blogdemo -type l ! -exec test -e {} \; -print

正如预期的那样,输出将与最后一个样本相同:

blogdemo/cyclic-link
blogdemo/dir-1/cyclic-link
blogdemo/dir-1/filex.txt
blogdemo/dir-1/dir-2/link-to-nonexistent-directory
blogdemo/dir-1/dir-2/dir-3/file-4.txt

让我们分解一下这里发生的事情:

  • find命令正在查找类型为链接的文件,就像我们在上一个示例中所做的那样
  • *!*正在否定 - exec表达式的结果,该表达式正在测试文件是否存在 - 否定将仅显示不存在的文件
  • exec表达式操作用于为每个找到的文件执行命令。在这种情况下,我们为每个文件执行test -etest 是一个用于检查文件类型和比较值的 Linux 命令。使用*-e*参数,我们正在检查文件是否存在
  • *{}*将被当前文件名替换
  • **用于保护命令不被 shell 扩展——可以引用命令以避免使用“ ** ”
  • ; 代表命令的结束
  • -print将结果打印到标准输出

3.3. 便携和深入的方式

或者,我们可以在许多网站上找到这个标准解决方案:

find -L blogdemo -type l

事实上,它比上述其他解决方案更有效。这是因为它还报告“文件系统循环”,我们可以在第二行看到:

find: ‘blogdemo/cyclic-link’: Too many levels of symbolic links
find: File system loop detected; ‘blogdemo/infinite-loop’ is part of the same file system loop as ‘blogdemo’
find: ‘blogdemo/dir-1/cyclic-link’: Too many levels of symbolic links
blogdemo/dir-1/dir-3/file-4.txt
blogdemo/dir-1/filex.txt
blogdemo/dir-1/dir-2/link-to-nonexistent-directory
blogdemo/dir-1/dir-2/dir-3/file-4.txt

许多人不知道的副作用是,如果链接指向目录,这种方法会进行深入搜索。

例如,假设我们有一个指向*/usr/share的链接。使用-L选项将使find遍历整个/usr/share*结构。

这种方法可能需要太多时间和资源才能完成。在大多数情况下,这不是我们想要做的。了解何时使用每种方法并牢记其好处和后果至关重要。

因此,如果我们想要在有指向目录的链接时搜索目录内的断开链接,我们可以使用-L*选项。*

但是如果我们想留在我们特定的目录结构中并且不想跟随链接,我们不需要使用*-L*。

要查看这种差异,我们可以启用调试以显示访问的每个文件和文件夹:

find -D search blogdemo -xtype l
find -D search -L blogdemo -type l

3.4. 骇客之道

我们可以使用不同的方法,使用用户权限级别来读取文件。

这有点像 hack,因为我们会看到损坏的链接以及我们无权读取的文件。换句话说,此选项仅适用于 root 用户。

也就是说,我们可以使用以下命令来查找损坏的链接:

find blogdemo -type l ! -readable

这将产生类似于上一个示例的输出:

blogdemo/cyclic-link
blogdemo/dir-1/cyclic-link
blogdemo/dir-1/filex.txt
blogdemo/dir-1/dir-2/link-to-nonexistent-directory
blogdemo/dir-1/dir-2/dir-3/file-4.txt

在这种情况下,我们使用*-type l*来查找符号链接类型的文件。

然后我们用*!否定-readable*参数。这将显示我们无法读取的文件。

由于我们无法读取损坏的链接,因此这些链接将作为结果的一部分返回。

3.5. 限制范围和深度

我们可以使用一些有用的测试表达式来限制搜索范围:

  • lname 模式:我们可以提供链接名称模式
  • ilname 模式:与lname相同,但不区分大小写
  • maxdepth:搜索到此目录深度
  • mindepth:从此目录深度搜索

例如,我们可以执行:

find blogdemo -mindepth 3 -ilname "*.TXT" -xtype l

这将产生输出:

blogdemo/dir-1/dir-2/dir-3/file-4.txt

3.6. 自定义输出

我们可以自定义输出以提供更多有用的信息。 使用表达式 -ls,我们可以获得有关链接及其指向位置的详细信息:

find blogdemo -xtype l -ls

输出将是:

find: ‘blogdemo/cyclic-link’: Too many levels of symbolic links
find: ‘blogdemo/dir-1/cyclic-link’: Too many levels of symbolic links
 21109100      0 lrwxrwxrwx   1  fabio    fabio          12 Sep 17 23:26 blogdemo/dir-1/filex.txt -> ../filex.txt
 21109086      0 lrwxrwxrwx   1  fabio    fabio          30 Sep 17 23:21 blogdemo/dir-1/dir-2/link-to-nonexistent-directory -> blogdemo/nonexistent-directory
 21109087      0 lrwxrwxrwx   1  fabio    fabio          16 Sep 17 23:21 blogdemo/dir-1/dir-2/dir-3/file-4.txt -> dir-4/file-4.txt

当文件名不寻常 时,这种方法效果不佳,因为它们可以包含除*\0/*之外的任何字符,甚至换行符。

文件名中的不寻常字符可能会对我们的终端造成意想不到且通常不受欢迎的事情。例如,某些字符可以更改我们在某些终端上的功能键的设置。