双方向型ファイルシステム同期ツール DirSync ProとUnison

 rsyncは誰もが知り愛用しているコマンドだ。ディレクトリー・ツリーのクローンをほかのディスクやシステムに作成し、変化した部分だけを送る無駄のない方法でクローンを最新状態に保つことができる。しかし、ときには逆方向に同期させたいこともある。そんなときに役立つのが双方向型ファイルシステム同期ツールだ。双方向型の同期ツールには基準とすべきファイルシステムはない。一致させるべきディレクトリー(クローン)を2つ指示するだけだ。ここでは、 DirSync Pro Unison という2種類の双方向型ファイルシステム同期ツールを紹介する。

 筆者は個人用データ同期ツールとしてUnisonを使っているが、ここでは、そうした事情は抜きにして紹介する。

 DirSync ProもUnisonも、対象とする2つのディレクトリーを設定するとディレクトリーの内容をサブディレクトリーも含めて同期させる。以下では、簡単なテストを行って、両ツールの動作を調べてみよう。まず、どちらのクローン上でも編集されているファイルの扱い方を見る。そのために、conflict-testというディレクトリーを作り、その下に2つのディレクトリーdir1とdir2、そして今日の日付を含むファイルdf1.txtを作った。両クローン上にあるこのファイルを内容は同じだが更新日時は異なるという状態にし、それぞれのツールの動作を調べるのだ。また、4行から成るファイルtestfile.txtも作った。このファイルを両クローン上で編集し、それぞれのツールの動作を調べるためだ。テストの際は、初めに同期操作を実行しdir1とdir2を相互に完全コピーさせた。

 次に、Linuxマシンで使われる可能性のあるファイル・タイプの扱い方を見る。そのために、dir1linux-fs-testというディレクトリーを作り、その下にディレクトリーdir1とdir2を作った。dir2は空のままだが、dir1にはhas-hardlink.txtとそれへのハードリンクhas-hardlink2.txt、そしてmyfifoというFIFOファイルを作成した。FIFOファイルというのは、2つのプロセスがこのファイルを同時にオープンして読み書きすることで双方向の通信を行うためのファイルだ。FIFOファイルはファイルシステムに存在するが、普通のファイルのようにディスクには保存されず、通信のためだけに存在する。FIFOファイルは多用されるものではないが、何かのアプリケーションがhomeディレクトリーのどこかでFIFOファイルを使っている可能性がある。そうしたhomeディレクトリー全体を同期させる場合を考えると、FIFOファイルの扱いを見ておく必要がある。

$ ls -lhF dir1
-rw-rw-r-- 1 ben ben 29 2008-11-19 11:19 df1.txt
lrwxrwxrwx 1 ben ben  7 2008-11-19 11:19 df2.txt -> df1.txt
-rw-rw-r-- 2 ben ben 29 2008-11-19 11:21 has-hardlink2.txt
-rw-rw-r-- 2 ben ben 29 2008-11-19 11:21 has-hardlink.txt
prw-rw-r-- 1 ben ben  0 2008-11-19 11:22 myfifo|

DirSync Pro

 DirSync Proは、Javaで書かれた単方向および双方向型のディレクトリー同期ツールだ。GUIを使って簡単に複数の同期タスクを設定し、1つまたは複数の同期タスクを実行することができる。ネットワーク転送や暗号化はサポートしていない。同じマシン上にあるディレクトリー同士の同期を意図したツールであり、ネットワークを介した同期にはNFSまたはSSH Filesystemが必要になる。

 DirSync Proは、Ubuntu Intrepid、Fedora 9、openSUSE 11のリポジトリーには含まれていない。そこで、DirSyncPro-1.0-Linux.zipを64ビットFedora 9マシンにダウンロードして、バージョン1.0 Finalをインストールした。このzipファイルにはコンパイルしたJavaクラス・ファイルが含まれているため、インストールは、DirSyncProをいずれかに置きそれを起動する小さなスクリプトを作れば完了する。

$ cd
$ unzip /FromWeb/DirSyncPro-1.0-Linux.zip
$ mkdir -p bin
$ ln -s ln -s ~/DirSyncPro-1.0-Linux/dirsyncpro.sh  ~/bin/DirSyncPro
$ chmod +x ~/bin/DirSyncPro
$ vi ~/bin/DirSyncPro
...
# get dirsync home
#DIRSYNC_HOME="$(dirname $0)"
DIRSYNC_HOME="$(echo ~/DirSyncPro-1.0-Linux/)"
...

$ ~/bin/DirSyncProx

 GUIの主要部にはタブが3つある。同期操作の結果を表示するためのタブと、同期タスクを作り設定するためのタブと、同期操作の全般的な属性を設定するためのタブだ。下に示したスクリーンショットは、homeディレクトリーの下にあるorigとnewというディレクトリーを使って同期をテストするための同期タスクを設定しているところ。「Same as default settings」チェックボックスをオンにすると、それ以降の設定項目がすべて無効になり、「Default settings」タブにある同期のための設定が適用される。ここで、2つのディレクトリー・パスの間にあるボタンに注目してほしい。スクリーンショットでは、左から右に向かう青い矢印になっているが、これはorigからnewへの単方向型同期であることを表す。このボタンをクリックすると、右向きの単方向型同期、左向きの単方向型同期、双方向型同期が順に切り替わる。

DirSync Pro(「Dir settings」タブ)

 同期させたいときは、「Dir settings」タブで同期タスクを選び、ツールバーにある「再生」ボタンを押す。同期操作が始まると「Output」タブに自動的に切り替わり、同期の進行に合わせてその詳細が表示される。

 次に、conflict-testシナリオの同期タスクを設定した。そして、まず初期化の同期を実行し、dir1とdir2の内容が認識されていることを確認した。双方のファイルがともに更新されている場合の処理方法は「Default settings」タブで設定する。選択肢は、更新日時の新しいファイルをコピーする(デフォルト)、サイズの大きい方のファイルをコピーする、名前を変えて両方のファイルをそれぞれのクローンにコピーする、警告メッセージのみの4つあり、ここでは最後の「警告のみ」を選んだ。そして、それぞれのクローンでdf1.txtにtouchしtestfile.txtを編集してから同期を実行した。その結果を下に示す。これを見ると、双方のファイルで修正日付が異なっていても、バイト単位で比較して内容の変更の有無を調べることはしていないようだ。

DirSync Proの「Output」タブ

 同期タスクはコマンドラインから実行することもできる。たとえば、~/bin/DirSyncPro -sync -nogui ~/NewDirSyncFile.dscのように、構成ファイルの名前(NewDirSyncFile)を指定しオプションをいくつか付けて実行すると、その構成ファイルに設定されているアクティブな同期タスクがすべて実行される。この構成ファイルは、GUIのメニューからFile→Save As fromの順にクリックして作成する。

 ところで、「Dir settings」タブのスクリーンショットを見た際、一覧になっている同期タスクの横に小さなチェックボックスがあるのに気づいただろうか。構成ファイルで実行する同期タスクは、このチェックボックスで指定する。

 次に、linux-fs-testを実行した。この同期タスクは当初から双方向に設定してある。シンボリック・リンク(ソフトリンク)の扱い方は、「Default settings」タブで設定する。選択肢は、何もしない、ファイルとしてコピーする(デフォルト)の2つだ。ここでは、無視したくなかったので、デフォルトを選んだ。

 初期化の同期が終わってから、dir2を見てみると、そこには4つのファイルがあった。FIFOは何の警告もなく無視され、ハードリンクは保存されず、ソフトリンクは設定どおりファイルになっていた。

 この結果を見て思いついたことがある。dir1のhas-hardlinkファイルから作られたdir2の2つのファイルの一方を更新し同期したらどうなるだろうかと思ったのだ。そこで、dir2で下に示したような編集をし同期させてみた。すると、dir1では2つのhas-hardlink*ファイルの更新日時はいずれも新しくなっていた。同じファイルへのハードリンクだから当然だ。一方、dir2に変化はなかった。2つのhas-hardlink*ファイルはdir1ではハードリンクだがdir2では異なるファイルだから、再度同期させると、今度はdir2のhas-hardlink.txtが更新された。

dir2$ date > has-hardlink2.txt
dir2$ cat has-hardlink*
Wed Nov 19 11:34:00 EST 2008
Wed Nov 19 11:21:24 EST 2008

 このテストの結果から、DirSync Proではディレクトリーにソフトリンクやハードリンクが含まれている場合は注意が必要だということがわかる。つまり、DirSync Proの双方向型同期の作りは単純で、2つのディレクトリーを入れ替えて同期しているということだ。

Unison

 Unisonは、OCamlで書かれた単方向および双方向型のディレクトリー同期ツールだ。GTKグラフィカル・インタフェースを搭載し、ターミナルから実行することもできる。

 パッケージはUbuntu Intrepid、openSUSE 11(1-Click)、Fedora 9(unison2279)、最新のMaemo機器向けが用意されている。試用機は64ビットFedora 9マシンなので、unison227パッケージをインストールした。

 unisonを実行すると、初回は、Root選択ウィンドウが開き、同期すべき第1(ローカル)ディレクトリーを尋ねてくる。ディレクトリーを入力し「OK」をクリックすると、第2ディレクトリーを尋ねる第2のダイアログが開く。このダイアログには宛先をローカル、SSH、RSH、ソケットのいずれかにするかを指定するオプションがある。中でも興味深いのは、ローカル・ディレクトリーとSSHパスだ。

 この2つのダイアログに答えるとメイン・ウィンドウが現れる。同時に、大きな警告ダイアログが開き、この同期タスクにはアーカイブ・ファイルがないと苦情を言われるが、一度も同期したことがなければ無視すればよい。同期したことがあるのにこの警告が表示されたとすれば、これは同期履歴の保存に使われているメタデータが損傷したことを意味する。こういうときは、メタデータをすべて削除し、バックアップし、同期を取り直すのが最善の策だ。メタデータは~/.unisonにあり、ファイル名はar2d40b01e31463631ab1c34274eb8ccdeといった形をしている。ほかのマシンと同期を取っている場合は、両方のマシンで~/.unisonにあるこのファイルを削除すること。

 主となるウィンドウを下に示す。主要部の一覧は、2つのクローンを比較して抽出した、変化したファイル、新たに作られたファイル、削除されたファイルだ。このスクリーンショットではクローンのディレクトリー名はnewとorigで、一覧の第1欄と第3欄にその名がある。それに挟まれた「Action」欄は同期操作で行われる動作を表す。この場合は、ディレクトリーnewが空のため、ディレクトリーccodとtrashをnewディレクトリーにコピーし、両ディレクトリーを一致させるように動作する。

Unisonのメイン・ウィンドウ

 2つのクローンを同期させるときは、「Go」ボタンをクリックする。同期処理の進捗は一覧の行ごとに「Status」欄に表示される。これはインターネット経由で同期タスクを実行しているときに便利だ。同期が完了すると、各行の「Status」欄に緑が点滅し、ウィンドウの下部に完了メッセージが表示される。この状態でツールバーの「Restart」をクリックすると、直ちに、同期済みである旨が表示され、一覧は空になる。

 同期操作での動作は、ツールバーのボタンで変更することができる。たとえば、あるファイルが両方のクローンにあり、ディレクトリーorigのものは変更されているとする。この場合、デフォルトでは、更新されているファイルがnewクローンにコピーされる。しかし、一覧でそのファイルを選び「Left to Right」ボタンをクリックすると、デフォルトとは逆に、newクローン(左)からorigクローン(右)にコピーすることができる。

 ファイルの新旧が競合した場合の措置は、「Actions」メニューで指定する。指定されたクローンからコピーする、あるいは、常に更新日時の最も新しいものを使うのいずれかだ。「Ignore」メニューで、同期から除外するファイルを指定することもできる。あるディレクトリーの下にあり指定した拡張子を持つファイルを除外する、あるいは、ディレクトリーに関わらず指定した名前を持つファイルを除外することができる。

 次に、冒頭で説明したconflict-testを実行した。その結果、更新日時だけが異なっているdf1.txtについては、日時の違いは無視された。両クローンで変更されているtestfile.txtについては、どちらも変更されていることを示す疑問符が「Action」欄に表示された。testfile.txtの行を選択して「Diff」ボタンをクリックすると下のスクリーンショットに示したようなウィンドウが現れる。これを見て、ツールバーにあるボタンから、左のバージョンを使う、右のバージョンを使う、何もしない、マージする、のいずれかを選ぶ。「Merge」(マージする)を選択すると「Action」欄に大きな「M」が表示される。ただし、マージ機能を使うときは、あらかじめマージのプレファレンスで、実行方法を設定しておく必要がある。

Unisonにおけるコンフリクトテスト

 GUIを表示せずにUnisonを動かせば、自動同期処理を行うこともできる。そこで、上に示した同期タスクからUnisonでconflict-test同期プロファイルを作成してみた。そして、「unison -batch -ui text conflict-test」というコマンドを実行すると、プロファイル中の競合していないファイルの同期処理が行われる。-batchオプションを付けないで実行すると、競合ファイルの処理方法を順次尋ねてくる。

 次に、linux-fs-test同期テストを行ったところ、myfifo以外のファイルはコピーされた。myfifoファイルは、一方のクローンでは必ず一覧に登場するが、他方のクローンでは登場しない。したがって、一覧上でこのファイルを選択し、メニューからIgnore→Permanently ignore this pathの順にクリックして除外しておくとよいだろう。

 myfifoファイルはコピーされなかったが、ソフトリンクは保存された。ハードリンクはdir2クローンでは何の警告もなく切れ、同じ内容のファイルhas-hardlink2.txtとhas-hardlink.txtができた。この2つのファイルにハードリンクの関係はない。Unisonの解説書を見ると、ハードリンクは取り扱えないとあるので、ハードリンクを保存する方法はない。

まとめ

 Linuxカーネルの機能を利用してリモートにあるさまざまなものをファイルシステムとしてマウントすれば、それに対してDirSync ProやUnisonを適用することができる。しかし、SSHを介したリモート・ファイルシステムの同期はきわめて有用であり、Unisonがその大きな特長としてこの機能を直接サポートしている点を挙げているほどだ。シンボリック・リンクを保存したいときは、現時点では、Unisonがよい。Javaランタイムを含みカーネルの機能を利用してリモートにあるものをマウントできるモバイル機器なら、DirSync Proが使える。しかも、高速だ。競合したファイルのマージの仕方を設定し自動処理したければ、Unisonで実現できる。

Ben Martin 10年以上にわたってファイルシステムに携わっている。博士課程を修了し、現在、libferris、ファイルシステム、検索ソリューションを中心にコンサルティングをしている。

Linux.com 原文(2008年12月3日)