如何在Perl哈希中表示文件系统的符号链接?

时间:2010-02-23 17:29:12

标签: perl tree filesystems cpan infinite-loop

在服务器故障上,How to list symbolic link chains?(不是我的问题)谈到列出所有符号链接并跟踪它们。为了做到这一点,我们首先考虑一个目录。

我想编写一个执行此操作的简短实用程序。将符号链接中的对放入哈希值然后处理哈希值很容易。

但后来我可能会有这样的事情:

ls -l
total 0
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 a -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 08:48 b -> c
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:03 c -> a
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 trap -> b
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 x -> y
lrwxrwxrwx 1 pjb pjb 1 2010-02-23 09:17 y -> b

很明显,a->b->c是一个循环,并且该陷阱指向一个循环,但要知道x指向一个循环,我需要稍微关注一下。

一个哈希表示是:

a => b
b => c
c => a
trap => b
x => y
y => b

但是一旦我知道循环是什么,反向表示更好地将循环标记为坏起点。

所以这里有一些问题:

  • 哈希是表示符号链接的最佳结构吗?
  • 分离文件系统图形的最佳方法是什么是将循环组件从树组件告诉树枝与循环类型的碎片?
  • 是否有比从所有起点手动搜索所有循环更好的算法?
  • 从图论理论的角度来看 - CPAN已经有了这种事情吗?如果没有,有什么好帮手模块?

3 个答案:

答案 0 :(得分:7)

您可以使用CPAN上的Graph模块,如下所示:

#! /usr/bin/perl

use warnings;
use strict;

use Graph;

my $g = Graph->new;
my $dir = @ARGV ? shift : ".";

opendir my $dh, $dir or die "$0: opendir $dir: $!";
while (defined(my $name = readdir $dh)) {
  my $path = $dir . "/" . $name;

  if (-l $path) {
    my $dest = readlink $path;
    die "$0: readlink $path: $!" unless defined $dest;

    $g->add_edge($name => $dest);
  }
  else {
    $g->add_vertex($name);
  }
}

my @cycle = $g->find_a_cycle;
if (@cycle) {
  $" = ' -> '; #" # highlighting error
  print "$0: $dir: at least one cycle: @cycle\n";
}
else {
  print "$0: $dir: no cycles\n";
}

例如,在与您的问题中的结构类似的目录中,输出为

$ ../has-cycle 
../has-cycle: .: at least one cycle: c -> a -> b

答案 1 :(得分:2)

查看CPAN模块File::Spec::Link。 resolve方法表示它会反复遍历链接以查找链接目标。

模块的解析方法可以这样说:

  

<强>决心($链路)
  通过反复调用linked返回最终链接到$ link的非链接。如果无法解析链接,则返回undef

我曾使用这个模块来找到符号链接的目标,其目标又是一个符号链接等等。但我不确定这是否会检测到循环符号链接。

答案 2 :(得分:-1)

您需要存储的不仅仅是链接的名称。获取inode编号(如果您的FS支持)或其他一些独特的方面。如果不存在,则考虑创建自己的,可能通过校验名称/创建/最后修改日期。无论哪种方式,您都需要一些方法来唯一标识每个链接。我已经看到一些实用程序只是限制链接数量(8到255之间)并声明任何超过此限制的循环,但我一直认为这是“以便宜的方式”。 :)