8

サーバー障害で、シンボリックリンクチェーンを一覧表示する方法は? (私の質問ではありません) すべてのシンボリック リンクを一覧表示し、それらをたどることについて話します。これを実行可能にするために、最初に単一のディレクトリを考えてみましょう。

これを行う短いユーティリティを書きたいと思います。シンボリック リンクのペアをハッシュに入れ、ハッシュを処理するのは簡単に見えます。

しかし、次のようなものがあるかもしれません:

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ポイントを知るには、少し従う必要があります。

1 つのハッシュ表現は次のとおりです。

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

しかし、ループが何であるかがわかれば、ループを不適切な開始点にマークするには、逆の表現の方が適しています。

そこで、いくつか質問があります:

  • ハッシュはシンボリックリンクを表現するのに最適な構造ですか?
  • ファイルシステムのグラフを分離して、ツリーコンポーネントからループタイプの小枝にルーピーコンポーネントを伝える最良の方法は何ですか?
  • すべての開始点からすべてのループを手動で検索するよりも優れたアルゴリズムはありますか?
  • グラフ理論の観点から -- この種のものはすでにCPANにあるのでしょうか? そうでない場合、良いヘルパー モジュールは何ですか?
4

3 に答える 3

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: .: 少なくとも 1 つのサイクル: c -> a -> b
于 2010-02-23T18:39:41.583 に答える
2

CPAN モジュールFile::Spec::Linkを見てください。resolve メソッドは、リンクを繰り返しトラバースして、リンクされたターゲットを見つけることを示しています。

モジュールの resolve メソッドには、次のように書かれています。

resolve($link)
  linked を繰り返し呼び出して、$link によって最終的にリンクされた非リンクを返します。リンクを解決できない場合は undef を返します

このモジュールを使用して、ターゲットがシンボリックリンクなどであるシンボリックリンクのターゲットを見つけました。しかし、これが循環シンボリックリンクを検出するかどうかはわかりません。

于 2010-02-23T17:46:17.013 に答える
-1

リンクの名前だけでなく、それ以上のものを保存する必要があります。iノード番号(FSがそれをサポートしている場合)またはその他の固有の側面を取得します。存在しない場合は、おそらく名前/作成/最終更新日のチェックサムによって、独自のものを作成することを検討してください。いずれにせよ、各リンクを一意に識別する何らかの方法が必要です。リンクの数 (8 から 255 の間) を単純に制限し、この制限を超えるものはすべてループと宣言するいくつかのユーティリティを見てきましたが、私は常にそれを「安価な方法を取る」と考えていました。:)

于 2010-02-23T20:07:35.240 に答える