jdupesの4つの重複排除方式を詳解:CoW、シンボリックリンク、ハードリンク、削除

ファイルシステムの観点からjdupesの-B、-l、-L、-dを解説し、それぞれの動作、安全上の境界、検証方法、削除やリンクに伴う事故の防ぎ方を整理します。

jdupes 重複ファイルを見つけたら、次の 4 つのまったく異なる方法でそれらに対処できます。

  • -B --dedupe: 重複ファイルが基礎となるデータブロックを共有できるようにします。
  • -l --link-soft: 重複したコピーを相対シンボリックリンクに置き換えます。
  • -L --link-hard: 重複したコピーをハードリンクに置き換えます。
  • -d --delete: 保持するファイルを対話的に選択し、残りのコピーを削除します。

これら 4 つのオプションはいずれも重複データを削減できますが、単に異なる方法で記述された 4 つの「重複ファイルの削除」として理解することはできません。

データブロック、inode、パス参照、ディレクトリエントリなど、さまざまなレベルでオブジェクトを変更します。

選択を誤った場合に最も問題となるのは、多くの場合、その場でエラーが報告されることではなく、数か月後にプログラムがファイルを変更、移動、または削除した後に、他のパスも影響を受けていることが判明することです。

この記事では、ファイルシステムの仕様と動作から始まり、4 つのモードの実際の違い、適用可能なシナリオ、制限事項、検証方法について説明します。

特別な注意事項: jdupes -d はファイルを削除する操作です。シンボリックリンクのトラバーサル動作を十分に理解せずに、コマンドラインに同じディレクトリを繰り返し書き込まないでください。また、-d-s または --symlinks とともに使用しないでください。

まず結論:4つの方式の主な違い

オプション 処理結果 パスが保存されるかどうか inodeは独立していますか? その後の変更は相互に影響を及ぼしますか? 主な制限事項
-B --dedupe 同じ物理データブロックを共有する すべて保持 はい 通常は影響を受けませんが、書き込み時に CoW が切断されます ファイルシステムは重複排除またはクローン作成インターフェイスをサポートしている必要があります
-l --link-soft コピーは相対シンボリックリンクになります パス名は残りますが、タイプはシンボリックリンクになります。 シンボリックリンク自身の inode、コンテンツはターゲットから取得されます リンクが指すコンテンツを変更すると、ターゲットファイルが変更されます ターゲットを移動または削除すると、リンクが壊れる可能性があります。
-L --link-hard 同じ inodeを指す複数のパス すべて保持 いいえ 本質的に同じファイルなので影響します ファイルシステムをまたぐことはできません。アプリケーションのセマンティクスは変更される可能性があります
-d --delete 保存対象として選択されていないコピーを削除する 選択したパスのみを保持する 適用できない 連携はされませんが、削除されたパスは完全に消えます。 間違ったものを選択すると、パスとメタデータが直接失われます。

一文しか覚えていない場合は、次のように判断できます。

  • 各ファイルを独立させ、ファイルシステムが CoW をサポートするようにするには、-B を優先します。
  • 同じファイルをまとめて表す複数のファイル名が明示的に必要です。-L を考慮してください。
  • 一部のパスを別のファイルへの単なる参照にしたい場合は、-l を検討してください。
  • 重複パス自体に保持する価値がないことを確認してから、-d のみを使用します。

jdupesが2つのファイルを同一と判定する仕組み

処理方法は異なりますが、先ほどの重複ファイル特定処理は同じです。

jdupes 公式マニュアルによると、デフォルトのマッチング プロセスには次のものが含まれます。

  1. ファイルサイズを比較します。
  2. 部分的なファイル ハッシュを比較します。
  3. 完全なファイル ハッシュを比較します。
  4. 最後に、バイトごとの比較が実行されます。

これらの段階を通過したファイルのみが、同じ重複ファイル コレクションに追加されます。

したがって、デフォルトモードは「ファイル名が同じであれば重複していても実行する」ではなく、また「ハッシュが同じであれば直ちに操作を実行する」でもありません。

アクション オプションを指定しないと、jdupes はデフォルトで重複ファイル セットのみを出力します。

1
jdupes -r /srv/data

異なるセットは空白行で区切られます。

実際に -B-l-L、または -d を使用する前に、読み取り専用スキャンを実行して、パス範囲と一致結果が期待どおりであることを確認する必要があります。

高速化のために最終検証を省略しない

-Q --quick はバイトごとの確認をスキップし、ハッシュ結果のみに依存します。

公式マニュアルには、データ損失のリスクとして明確にフラグが立てられています。

-T --partial-only は、ファイルの先頭の部分ハッシュのみと一致するため、より危険です。

削除、リンク、または CoW 重複排除を実行する場合、スキャン時間を短縮するために、これら 2 つのオプションをランダムに含めるべきではありません。

この記事の後続の例はすべて、デフォルトの完全な確認プロセスを使用します。

-B --dedupe:独立したファイルのままデータブロックを共有する

基本的なコマンドは次のとおりです。

1
jdupes -r -B /srv/data

-B は、重複ファイルに対して低レベルの重複排除を実行するようにファイルシステムに要求します。

公式マニュアルでは、このプロセスをコピーオンライト、CoW、クローン作成、またはreflink 重複排除と呼んでいます。

ディレクトリ レベルでは、元のファイル名がそのまま残ります。

inode レベルから見ると、これらは依然として別個のファイルです。

データブロック レベルから見ると、同じコンテンツが同じ物理ブロックのセットを参照できるため、実際に占有されるスペースが削減されます。

重複排除後の CoW 構造

2 つの同一のファイルがあるとします。

1
2
/srv/data/a.iso -> inode 1001 -> 数据块 A、B、C
/srv/data/b.iso -> inode 2002 -> 数据块 A、B、C

2 つのパスは異なる inodeに対応しますが、同じエクステントが基礎となるデータブロックを共有します。

b.iso の一部が後で変更された場合、CoW 対応ファイルシステムは変更されたセクションに新しいブロックを割り当てます。

1
2
/srv/data/a.iso -> inode 1001 -> 数据块 A、B、C
/srv/data/b.iso -> inode 2002 -> 数据块 A、X、C

変更されていないセグメントは共有されたままですが、書き込みは切り離されます。

これは、-B とハードリンクの最も重要な違いです。

後から変更される可能性があるファイルに適する理由

ハードリンクを使用する場合、複数のパスは実際には同じ inodeになります。

プログラムは任意のパスを通じてコン​​テンツを適切な場所に書き込み、他のパスから見えるコンテンツも変更されます。

CoW 重複排除を使用する場合、ファイルは独立したままになります。

ファイルシステムが CoW を正しく実装している限り、1 つのファイルを変更しても別のファイルが同時に変更されることはありません。

したがって、一般的には、次のシナリオが -B により適しています。

  • 複数の仮想マシンイメージ。
  • 複数のバージョンのバックアップ ディレクトリ。
  • 写真またはビデオ映像のコピー。
  • ソフトウェア リポジトリ内のインストール パッケージが重複します。
  • 同じコンテンツを持つファイルですが、ライフサイクルが異なります。

-Bが要求するファイルシステム機能

-B ファイルの内容自体を再圧縮したり移動したりするのは jdupes ではありません。

これは、オペレーティング システムとファイルシステムによって提供される同じセグメント重複排除またはクローン作成インターフェイスに依存します。

公式マニュアルに記載されているサポート オブジェクトには次のものが含まれます。

  • Btrfs;
  • reflink 機能が有効になっている XFS。
  • アップルAPFS。

動作するかどうかは、カーネル、マウント環境、jdupes コンパイル機能、およびファイルシステムのフォーマット パラメーターによって異なります。

XFS の場合、ファイルシステム タイプが XFS であることを確認するだけでは十分ではありません。ファイルシステムの作成時に reflink 機能を有効にする必要があります。

最初にファイルシステムのタイプを確認できます。

1
findmnt -T /srv/data

XFS はファイルシステム情報をさらに表示できます。

1
xfs_info /srv/data

コマンドが明らかなエラーを報告しないからといって、すべての重複データが解放されたとは考えないでください。

CoW重複排除の結果を検証する方法

まず、ファイルにまだ異なる inodeがあることを確認します。

1
2
3
stat -c '%n inode=%i size=%s blocks=%b' \
  /srv/data/a.iso \
  /srv/data/b.iso

2 つの inodeが異なる場合、これは予期されます。

ただし、stat で表示されるブロック数は、共有セクションを直接正確に表現できない場合があります。

ファイルシステムが異なれば、共有ブロックのカウント方法も異なる場合があります。

重複排除の前後でファイルシステムの空き容量を比較することもできます。

1
df -h /srv/data

Btrfs の場合、ファイルシステム固有のツールを使用してスペース割り当てを観察できます。

1
btrfs filesystem usage /srv/data

テストでは、破棄可能なサンプルを使用し、ファイルの 1 つを変更して、もう 1 つのファイルのハッシュが変更されていないことを確認する必要があります。

-Bの制約

CoW の重複排除は「コストゼロ」ではありません。

共有セクションでは、参照関係を維持するためにファイルシステムが必要です。

後続の書き込みにより新しいブロック割り当てがトリガーされ、さらなる断片化が発生する可能性があります。

高頻度でランダムに書き込まれるデータ、データベース ファイル、または継続的に変更される仮想ディスクの場合は、書き込み増幅と断片化の影響を最初に評価する必要があります。

スナップショットにより、空間統計がより複雑になる場合もあります。

ディレクトリ内のファイルを削除した後、別のファイルまたはスナップショットによって参照されている場合、共有ブロックはすぐには解放されません。

Btrfs および NAS のシナリオに重点を置いている場合は、サイトの Btrfs + jdupes CoW 重複排除の実践 を引き続き参照してください。

基本的なコマンドは次のとおりです。

1
jdupes -r -L /srv/data

-L は、重複ファイルの各セット内の他のコピーを、最初のファイル inodeを指すハードリンクに置き換えます。

処理後も複数のパス名は存在しますが、それらは別個のファイルではなくなります。

ハードリンク後の構造

処理前:

1
2
/srv/data/a.bin -> inode 1001 -> 数据块 A、B、C
/srv/data/b.bin -> inode 2002 -> 数据块 A、B、C

処理後:

1
2
3
/srv/data/a.bin --+
                 +-> inode 1001 -> 数据块 A、B、C
/srv/data/b.bin --+

現時点では、a.binb.bin は、同じ inodeの 2 つのディレクトリエントリです。

これらは単なる「共有コンテンツ」ではなく、2 つの名前を持つ同じファイルです。

ハードリンクを変更するとどうなるか

プログラムが b.bin を直接開き、その中のバイトを上書きすると、a.bin によって読み取られる内容も変更されます。

どちらのパスも最終的には同じ inodeにアクセスするためです。

ファイル権限、所有者、タイムスタンプなどの inode メタデータは、互いに独立していなくなりました。

ただし、紛らわしい例外が 1 つあります。

一部のエディタでは、ファイルをその場で変更せず、一時ファイルを作成し、元のパスを名前変更で置き換えます。

この「新しいファイルを書き込んでから置換する」保存方法により、置換されたパスが新しい inodeを取得し、それによってハードリンク関係が解放されます。

したがって、1 回の編集テストだけでは、すべてのアプリケーションが同じように動作すると推測することはできません。

ハードリンクはファイルシステムをまたげない

ハードリンクは、同じファイルシステム内でのみ作成できます。

両方のマウント ポイントが ext4 を使用し、異なるデバイスまたはファイルシステム インスタンスを持っている場合でも、境界を越えてハードリンクを作成することはできません。

次のコマンドを使用して、デバイス番号と inodeを表示できます。

1
2
3
stat -c '%n device=%d inode=%i links=%h' \
  /srv/data/a.bin \
  /srv/data/b.bin

処理が成功した後は、両方のパスのデバイス番号と inode が同じになるはずで、通常はリンク数が増加します。

以下もご利用いただけます:

1
ls -li /srv/data/a.bin /srv/data/b.bin

ハードリンクのパスを1つ削除しても内容は直ちに消えない

b.bin を削除すると、ディレクトリエントリの 1 つが削除されるだけです。

a.bin がその inodeを指している限り、ファイル データはまだ存在します。

ファイルシステムは、最後のハードリンクが削除され、ファイルを開き続けるプロセスがない場合にのみ、対応するオブジェクトとデータブロックを再利用します。

これは、「目的のパスが消えた後にリンク切れが残る」シンボリックリンクとは全く異なります。

-Lが適する場面

ハードリンクは、前提条件が明確なシナリオに適しています。

  • ファイルは同じファイルシステム内にあります。
  • 実際、ビジネス用語では、複数のパスを同じオブジェクトとみなすことができます。
  • ファイルは読み取り専用であることが想定されており、そうでない場合、コンテンツはその場で変更されなくなります。
  • バックアップ、同期、インデックス作成、権利管理ソフトウェアはハードリンクを正しく処理します。
  • パスごとに個別の inode メタデータを用意する必要はありません。

典型的な例には、読み取り専用のパッケージ キャッシュ、不変のアーカイブ コピー、および制御されたメディア リポジトリが含まれます。

-Lを使用すべきでない場面

次の状況では、慎重に使用するか、使用を避けてください。

  • コピーはアプリケーションによってその場で変更される場合があります。
  • ファイルは異なるユーザーまたはアクセス許可ポリシーに属します。
  • バックアップ ソフトウェアは、ハードリンクをデータの複数のコピーに拡張する場合があります。
  • 同期ソフトウェアはハードリンク関係を保持しない場合があります。
  • アプリケーションはファイルを識別するために inodeの一意性に依存します。
  • ファイルは複数のファイルシステムまたはネットワーク マウント ポイントにまたがります。

2 つのパスが現在は同じ内容を持っていても、将来は責任が異なる場合、同じ内容を持っていても、それらが同じ inodeになる必要があるとは限りません。

基本的なコマンドは次のとおりです。

1
jdupes -r -l /srv/data

-l は、各グループの最初のファイルを保持し、他の重複ファイルをそれを指す相対シンボリックリンクに置き換えます。

処理前に以下があると仮定します。

1
2
/srv/data/original/report.pdf
/srv/data/archive/report-copy.pdf

処理後、2 番目のパスは同様の関係のように動作する可能性があります。

1
/srv/data/archive/report-copy.pdf -> ../original/report.pdf

実際の相対パスはディレクトリの場所によって決まります。

相対シンボリックリンクとは何か

シンボリックリンクは、ターゲット inodeの追加名ではなく、ターゲット パス テキストを保持します。

相対リンクの解析の開始点は、コマンド実行時の現在の作業ディレクトリではなく、シンボリックリンクが配置されているディレクトリです。

したがって、内部構造が変更されていないディレクトリ ツリーを移動する場合でも、通常は相対シンボリックリンクが引き続き機能します。

ただし、リンクだけ、またはターゲットだけを移動すると、関係が無効になる可能性があります。

シンボリックリンクとハードリンクの動作の違い

シンボリックリンクはファイルシステムにまたがることができます。

通常、ハードリンクはファイルシステムをまたぐことはできません。

シンボリックリンクには独自のファイル タイプと inodeがあります。

ハードリンクは、同じ通常のファイル inodeの別名にすぎません。

シンボリックリンク ターゲットを削除または名前変更すると、リンクが壊れる可能性があります。

ハードリンク名を削除しても、他のハードリンクが存在する限り、コンテンツには引き続きアクセスできます。

シンボリックリンクはディレクトリを指すことができます。この記事で説明する jdupes アクションは、ファイルの重複コレクションを対象としています。

シンボリックリンクにするとファイル種別が変わる

-l を実行する前は、両方のパスは通常のファイルでした。

実行後、そのうちの 1 つは通常のファイルのままで、他のパスはシンボリックリンクになります。

これは一部のアプリケーションに影響します。

  • セキュリティ ポリシーでは、次のシンボリックリンクを拒否する場合があります。
  • コンテナまたはサンドボックスにはリンク ターゲットが表示されない場合があります。
  • Web サービスは、リンクが指すパスへのアクセスを拒否する場合があります。
  • バックアップ ソフトウェアはリンク自体をバックアップすることしかできません。
  • ファイル監視プログラムは、リンクとターゲットに対して異なるイベントを生成する場合があります。
  • 権限チェックは最終的にターゲット パスとその親ディレクトリに対して行われます。

したがって、「ファイルが開ける」ということは、アプリケーションの互換性が確認されていることを意味するものではありません。

シンボリックリンクの検証方法

リンクによって保存されたターゲット テキストを表示します。

1
readlink /srv/data/archive/report-copy.pdf

最終目標を分析します。

1
realpath /srv/data/archive/report-copy.pdf

ディレクトリ ツリー内の壊れたリンクを確認します。

1
find /srv/data -xtype l -print

find -xtype l は、最終ターゲットが解決できないシンボリックリンクを検索します。

正式に使用する前に、対象ファイルの移動、上位ディレクトリの移動、バックアップとリカバリ、アプリケーションの読み込みなどの動作もテストする必要があります。

-lが適する場面

シンボリックリンクは、「参照関係が本質的に合理的である」シナリオに適しています。

  • 正式なコピーを明示的に指定したい。
  • 他のパスは本質的に単なるエントリ パスまたは互換性パスです。
  • ファイルシステム間の参照が必要です。
  • アプリケーションはシンボリックリンクを明示的にサポートします。
  • 対象パスのライフサイクルを保証できる。

シンボリックリンクは、ディレクトリ ツリーが頻繁に分割されたり、個別に同期されたり、個別にパッケージ化されたりする場合には、一般に理想的ではありません。

-d --delete:残す項目を選び、それ以外のコピーを削除する

基本的なコマンドは次のとおりです。

1
jdupes -r -d /srv/data

-d は、重複ファイルのセットごとに、どのパスを保持するかを選択するようユーザーに要求し、残りのパスを削除します。

これは 4 つの方法の中で最も直観的であり、最も元に戻すことができない方法です。

-B-L、および -l は、元のパス エントリを特定の形式で保持します。

-d は、実際には予約されていないファイルのディレクトリエントリを削除します。

重複内容の削除でも情報を失うことがある

2 つのファイルの内容がまったく同じであるという事実は、2 つのパスに値がないことを意味するわけではありません。

パスが異なれば、表現する内容も異なる場合があります。

  • ディレクトリの分類。
  • ファイル名のセマンティクス。
  • 所属するプロジェクト。
  • アクセス制御コンテキスト。
  • バックアップ保持ポリシー。
  • アプリケーションのインデックス関係。
  • ユーザーのワークフロー。

jdupes は、ファイルの内容が重複しているかどうかを判断しますが、どのディレクトリエントリがビジネス上重要であるかは判断しません。

したがって、削除する前にコンテンツとパスの両方を確認する必要があります。

最重要リスク1:同じディレクトリを重複指定しない

次のように実行しないでください。

1
jdupes -d /srv/data /srv/data

また、次のような異なる書き込み方法を使用して、同じディレクトリ ツリーを 2 回渡すことも避けてください。

1
2
cd /srv
jdupes -d data /srv/data

公式ドキュメントでは、同じディレクトリが複数回指定されると、同じファイルが「それ自体の複製」としてコレクションに表示される可能性があると警告されています。

ユーザーがこの混乱を招くコレクション内の 1 つの表示アイテムを保持し、同じ実ファイルを表す別の表示アイテムを削除すると、データが失われる可能性があります。

すべての入力パスは実行前に正規化され、重複、エイリアス、または予期しない重複がないことを確認する必要があります。

最初に実際のパスを確認できます。

1
2
realpath /srv/data
realpath ./data

また、バインドマウント、シンボリックリンク ディレクトリ、およびコンテナマッピングにも注目して、複数のエントリから同じコンテンツを走査できるようにします。

最重要リスク2:-d-sの併用

-s または --symlinks は、シンボリックリンク ディレクトリに従います。

これを -d と一緒に使用すると、対話型リストにシンボリックリンク関連のパスと参照されている実際のファイルの両方が表示される場合があります。

公式マニュアルには、ユーザーが誤ってシンボリックリンクを保持しているにもかかわらず、それが指すファイルを削除してしまう可能性があると記載されています。

その結果、パスは保持されているように見えますが、実際にはターゲットに到達できないリンクだけが残ります。

シンボリックリンクの関係を完全にマッピングして検証していない限り、次を使用しないでください。

1
jdupes -r -s -d /srv/data

より安全なアプローチは、最初にシンボリックリンクをたどるのではなく、実際のディレクトリとリンク構造を個別に確認することです。

-N --no-promptは削除を自動化する

-N--delete と一緒に使用すると、各グループの最初のファイルが自動的に保持され、残りのファイルが削除されます。

例えば:

1
jdupes -r -d -N /srv/data

これは通常の「確認をスキップする」のではなく、「誰が最初の項目であるか」をそのままリテンション戦略に変えます。

本当に自動化が必要な場合は、まず次のことを理解する必要があります。

  • -o name はデフォルトでファイル名でソートします。
  • -o time は変更時間で並べ替えることができます。
  • -i は並べ替えを逆にします。
  • -O --param-order は、結果セットに対するコマンドライン パラメーターの順序の影響を維持することを優先します。

自動削除する前に、同じパス、並べ替え、再帰オプションを使用して読み取り専用スキャンを実行し、結果を監査用に保存する必要があります。

信頼できるバックアップがないデータの場合、-d -N を直接使用することはお勧めできません。

4つの方式が権限とメタデータに与える影響

デフォルトでは、jdupes の主な目標は重複コンテンツを検出することです。

ただし、同じ内容のファイルでも、所有者、グループ、またはアクセス許可ビットが異なる場合があります。

-p --permissions では、異なる所有者、グループ、および権限を持つファイルが重複として扱われないように要求できます。

1
jdupes -r -p /srv/data

これは -L にとって特に重要です。

ハードリンク後は、複数のパスが inode メタデータを共有するため、異なる所有者と許可ビットを維持することができなくなります。

-d の場合、どのパスを選択して保持するかによって、どのファイル メタデータが最終的に残されるかが決まります。

-l の場合、コンテンツへのアクセスは最終的にターゲットファイルとパスのトラバーサル権限によって制御されます。

-B の場合、ファイル inodeは独立したままであるため、それぞれのアクセス許可とほとんどのメタデータは独立して存在し続けることができます。

ACL、拡張属性、SELinux タグ、またはファイル機能にも依存している場合は、対応するツールを使用して追加の検証を行う必要があります。

従来の許可ビットを比較するだけでは、すべての拡張メタデータがビジネス上の判断に組み込まれたことを意味するわけではありません。

ファイルシステムをまたぐ場合の選び方

複数のマウント ポイントをスキャンする場合、以下を結合できます。

1
jdupes -r -1 /srv/data /mnt/archive

-1 --one-file-system は、ファイルシステムまたはデバイス間での一致を防ぎます。

これにより、後続のアクションが機能の境界に遭遇する可能性を減らすことができます。

ファイルシステム間の 4 つのモードの違いは次のとおりです。

  • -B はファイルシステム インターフェイスと共有セグメント機能に依存しており、通常はターゲットが互換性の範囲内にある必要があります。
  • -L ファイルシステム間のハードリンクを作成できません。
  • -l は、ファイルシステム全体でパス参照を保存できますが、ターゲット マウントが見つからない場合、リンクは使用できません。
  • -d 別のファイルシステム上のコピーを削除できますが、保持されたアイテムが配置されているストレージが長期間使用可能であることを確認する必要があります。

たとえば、ローカル コピーを削除し、そのコピーのみをリムーバブル ハード ドライブまたは一時的なネットワーク マウントに保持することは、技術的には成功する可能性がありますが、ビジネス的には非常に危険です。

安全に実行するための手順

アクション オプションを運用ディレクトリに直接追加しないでください。

以下の順序で実行することを推奨します。

ステップ 1: バックアップまたはスナップショットが回復可能であることを確認する

スナップショットが存在するからといって、それを復元できるわけではありません。

少なくとも次のことを確認してください。

  • スナップショットには、今回スキャンされたすべてのディレクトリが含まれます。
  • スナップショットの作成時間は重複排除操作よりも前です。
  • スナップショットは、運用ディレクトリと同じ障害ドメインを共有しません。
  • 個々のファイルとディレクトリ全体を回復する既知の方法。
  • 復旧作業はスポットテストの対象となります。

ハードリンクとシンボリックリンクも、バックアップ ツールがリンク セマンティクスを保持していることを確認する必要があります。

ステップ 2: 入力パスが繰り返されていないことを確認する

スキャンする各ディレクトリをリストします。

1
2
realpath /srv/data/project-a
realpath /srv/data/project-b

次のことを確認してください。

  • 同じ実ディレクトリを指します。
  • 1 つのディレクトリには別のディレクトリが完全に含まれています。
  • シンボリックリンクを介して同じディレクトリ ツリーに再度入ります。
  • エイリアスはバインドマウントまたはネットワーク マウントを通じて表示されます。
  • シェルのワイルドカード拡張により重複します。

特に -d を使用する場合は、不明瞭な重複を最初に除去する必要があります。

ステップ 3: 最初に読み取り専用スキャンを実行する

1
jdupes -r /srv/data/project-a /srv/data/project-b

出力を監査ファイルに保存します。

1
2
jdupes -r /srv/data/project-a /srv/data/project-b \
  > /tmp/jdupes-review.txt

ここでは action オプションが使用されていないため、一致のセットのみが出力されます。

どのパスが独立したセマンティクスを保持する必要があり、どのパスが単なる冗長コピーであるかをグループごとに確認します。

ステップ4:小さなテストディレクトリで動作を検証する

破棄可能なテスト ディレクトリを作成します。

1
2
3
4
test_dir="$(mktemp -d)"
mkdir -p "$test_dir/a" "$test_dir/b"
printf 'jdupes test data\n' > "$test_dir/a/sample.txt"
cp "$test_dir/a/sample.txt" "$test_dir/b/sample.txt"

まず inodeとハッシュを確認します。

1
2
stat -c '%n inode=%i links=%h' "$test_dir"/*/sample.txt
sha256sum "$test_dir"/*/sample.txt

その後、一度に 1 つのアクションのみをテストします。

ハードリンクをテストします。

1
2
jdupes -L "$test_dir/a" "$test_dir/b"
stat -c '%n inode=%i links=%h' "$test_dir"/*/sample.txt

他のアクションをテストするには、クリーンなサンプルを再作成し、既にハードリンクされているファイルにテストをオーバーレイし続けないでください。

ステップ 5: 一度に 1 つのアクションを実行する

4 つの処理モードを同じコマンドにまとめないでください。

ディレクトリの責任に基づいてバッチを分割します。例:

1
jdupes -r -B /srv/data/mutable-archive
1
jdupes -r -L /srv/data/immutable-cache
1
jdupes -r -l /srv/data/compat-links
1
jdupes -r -d /srv/data/manual-review

これにより、結果の解釈、変更の確認、リカバリの実行が容易になります。

ステップ 6: 操作後の検証

どちらの方法を選択する場合でも、少なくとも次のチェックを実行してください。

1
jdupes -r /srv/data
1
find /srv/data -xtype l -print
1
df -h /srv/data

次に、モデルに基づいて検証を追加します。

  • -B: inodeが独立していること、および一方のコピーをサンプリングして変更した後、もう一方のコピーは変更されていないことを確認します。
  • -L: inodeが同じであり、リンク数が正しいことを確認します。
  • -l: readlink および realpath を使用してターゲットを確認し、壊れたリンクをチェックします。
  • -d: 監査リストに従って、予約されたパスがまだ存在していることを確認します。

最後に、実際にファイルを使用するアプリケーションに読み取り、インデックス付け、バックアップ、または同期テストを実行させます。

用途別の選び方

NAS メディア ライブラリと写真アーカイブ

基礎となるレイヤーが重複排除をサポートする Btrfs であり、ファイルが写真管理プログラムまたはメディア管理プログラムによって変更される可能性がある場合は、最初に -B を評価します。

独立したファイル セマンティクスを保持し、ハードリンクのリンクされた変更のリスクを軽減できます。

ディレクトリが完全に読み取り専用で、アプリケーションがハードリンクを正しく処理する場合は、-L も機能する可能性があります。

パッケージキャッシュとビルド成果物

-L は、不変のビルド アーティファクトが同じファイルシステム上にある場合、通常はシンプルで効率的です。

ただし、ビルド ツールがキャッシュされたファイルをインプレースで上書きする場合は、ハードリンクを回避する必要があります。

いつでも再生成できるキャッシュの場合は、-d を直接使用することもできますが、削除によってインデックスが破壊されないことを確認する必要があります。

複数世代のバックアップディレクトリ

マルチバージョン カタログでは、各バージョンが個別のビューを維持する必要があります。

CoW がサポートされている場合、-B は通常、-L よりもこのセマンティクスに準拠しています。

ハードリンクは増分バックアップにもよく使用されますが、ハードリンクはバックアップ プログラムによって体系的に管理される必要があり、「現在の内容が同じ」という理由で一時的に置き換えることはできません。

古いパスとの互換性

権限のあるファイルに複数のレガシー パスからアクセスする必要があり、ソフトウェアがシンボリックリンクをサポートしている場合は、-l を選択できます。

これは、他のパスは単なる参照であることをシステムに明示的に伝えることと同じです。

宛先パスは安定しており、バックアップ、コンテナー、およびアクセス許可のポリシーでカバーされている必要があります。

ダウンロードディレクトリの一括整理

複製コピーにディレクトリ セマンティクスがなく、バックアップが利用可能であることを確認するには、対話型 -d を使用します。

最初に読み取り専用スキャンを実行し、次に予約項目をグループごとに選択します。

いくつかのキーストロークを節約するためだけに、すぐに -N にジャンプしないでください。

よくある誤解

誤解1:4つの方式で節約できる容量はまったく同じ

不確かな。

-d-L-l は最終的に単なるプレーン ファイルになりますが、ディレクトリエントリまたはリンク オブジェクトの数と種類は異なります。

-B による実際の節約量は、正常に共有されたエクステント、ブロック サイズ、アライメント、スナップショット、およびその後のファイルシステムへの書き込みによって異なります。

誤解2:ハードリンクは単に信頼性の高いシンボリックリンクである

2 つは意味が異なるため、単純に「信頼性」で分類することはできません。

ハードリンクは、複数の名前を同じ inodeにバインドします。

シンボリックリンクは、解決可能なターゲット パスを保持します。

前者は「対象パスの名前変更時にリンクが切れる」という問題がありませんが、後者はファイルシステムを越えて参照関係を明確に表現できます。

誤解3:CoW重複排除後のファイルはハードリンクになる

いいえ。

CoW 重複排除後のファイルには依然として独立した inodeがありますが、一部またはすべてのデータブロックを共有します。

ハードリンクは、inode レベルでは同じファイルです。

この違いは、ls -li または stat で確認できます。

誤解4:内容が同じなら、どちらを削除しても安全である

同じ内容は、バイトが同じであることを証明するだけです。

パス、ファイル名、権限、ラベル、ビジネス所有権、バックアップ ポリシーは依然として異なる場合があります。

-d の選択は、ファイルの内容だけではなく、パスのセマンティクスに基づいて行う必要があります。

誤解5:相対シンボリックリンクは常に可搬性が高い

相対リンクは、リンクとターゲットが相対位置を維持している場合にのみ移植可能です。

サブディレクトリの 1 つだけをコピーすると、リンクがすぐに無効になる可能性があります。

パッケージ化、同期、コンテナーのマウントにより、元のディレクトリ関係が変更される場合があります。

誤解6:削除後はdfの空き容量が直ちに増える

不確かな。

ファイルはプロセスによってまだ開かれているか、スナップショット、他のハードリンク、または CoW 共有によって参照されている可能性があります。

ファイルシステムの遅延再利用とスペース アカウンティング方法も、観察された結果に影響を与えます。

参考資料

最終的な選択指針

ファイルシステムが CoW をサポートしており、後でファイルを個別に変更できるようにしたい場合は、通常、-B --dedupe が 4 つのオプションの中でファイルの独立性を保ちやすい選択です。

同じ不変ファイルへの複数のパスがすべて同じファイルシステム上に明示的に必要な場合は、-L --link-hard を使用します。

明確なパス参照関係を確立する必要があり、ターゲットの移動後にリンクが切断されるリスクを許容できる場合は、-l --link-soft を使用します。

冗長パス自体に保存価値がなく、信頼できる回復方法がすでに存在する場合は、-d --delete を使用します。

どちらを選択する場合でも、同じ原則に従う必要があります。

最初に読み取り専用スキャンを実行し、パスを確認し、アプリケーションの動作をテストしてからアクションを実行し、最後にファイルシステムと運用結果を検証します。

-d についても同様です。シンボリックリンク関係を十分に確認せずに、同じディレクトリを 2 回指定したり、-s または --symlinks と組み合わせたりしないでください。

保存されたストレージスペースは再購入できますが、失われたディレクトリセマンティクスと固有のコピーは再構築できない場合があります。