Как я могу представить символические ссылки файловой системы в хэше Perl? - PullRequest
8 голосов
/ 23 февраля 2010

При сбое сервера, Как составить список цепочек символических ссылок? (не мой вопрос) говорит о перечислении всех символических ссылок и их следовании. Чтобы сделать это выполнимым, давайте сначала рассмотрим один каталог.

Я хочу написать короткую утилиту, которая делает это. Выглядит просто, чтобы поместить пары из символических ссылок в хеш, а затем обработать хеш.

Но тогда у меня может быть что-то вроде:

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 ]

7 голосов
/ 23 февраля 2010

В CPAN есть модуль График , который вы можете использовать следующим образом:

#! /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
2 голосов
/ 23 февраля 2010

Посмотрите на модуль CPAN Файл :: Spec :: Link . Метод разрешения говорит, что он повторно просматривает ссылку, чтобы найти связанную цель.

Метод разрешения модуля имеет следующее:

Решимость ($ ссылка)
Возвращает не-ссылку, в конечном счете связанную с $ link, путем многократного вызова link. Возвращает undef, если ссылка не может быть разрешена

Я использовал этот модуль, чтобы найти цель символической ссылки, целью которой была символическая ссылка и так далее. Но я не уверен, обнаружит ли это циклические символические ссылки.

0 голосов
/ 23 февраля 2010

Вам нужно хранить больше, чем просто название ссылки. Либо захватите номер инода (если ваш FS это поддерживает), либо какой-то другой уникальный аспект. Если он не существует, подумайте о создании своего, возможно, путем проверки контрольной суммы имени / создания / даты последнего изменения. В любом случае, вам нужен какой-то способ уникальной идентификации каждой ссылки. Я видел некоторые утилиты, которые просто накладывают ограничение на количество ссылок (между 8 и 255) и объявляют все, что превышает это ограничение, циклом, но я всегда считал, что это «выбор дешевого выхода». :)

...