Unisonマニュアル - 仕様
Unison はシンプルな仕様に基づいています.
root
レプリカの root とは,ローカルマシン及びリモートマシンにおいて,同期を取るべきファイル群の場所を表わします.例えば
relative/path/of/root
はローカルマシンにおける root を,Unison が実行されたディレクトリからの相対パスとして表わし,
/absolute/path/of/root
はどこで Unison が実行されたかは関係無く,ローカルマシンのファイルシステムにおける絶対パスで root を示しています.リモートホストの root は,接続に用いるプロトコルによって ssh://,もしくは rsh:// を先頭に付け加えます.
ssh://remotehost//absolute/path/of/root rsh://user@remotehost/relative/path/of/root
リモートホストで Unison サーバが動いているのであれば,
socket://remotehost:portnum//absolute/path/of/root socket://remotehost:portnum/relative/path/of/root
こうように書くことで,クライアントの Unison が接続すべきリモートホストとポート番号を明示します.
root の書式は URI (RFC 2396) の書式に基づきます.
path にプロトコルを示すプレフィクスが付いていない場合,プロトコルは file: であると見なされます.Windows の場合,ファイル共有機能と file: プロトコルを用いてファイルの同期を取ることが出来ます.
unison foo //host/drive/bar
というように実行すると,ローカルの foo というディレクトリと,host というマシンの drive:\bar の同期を取ります*1.
root の名前は実行時に Unison によって内部的に変換されます.各 root に対応するアーカイブファイル名を特定するためです.つまり //saul//home/bcpierce/common と //saul.cis.upenn.edu/common は名前の違う同一のレプリカであると認識されます.
path
path とは同期を取るファイル群の中の一つを指します.レプリカの root からの相対パスで表わされます.
path は単なる / で区切られた名前の羅列です.Unison が動作する環境に関係無く,path の区切りは常に / (スラッシュ) であることに注意してください.ローカルのファイルシステムにおいて必要がある場合は,/ は \ (バックスラッシュ) に自動的に変換されます*2.
path が空の場合,レプリカ全体を表わします.Unison は空の path を [root] と表示します.
変更
あるレプリカのpath,p の指し示す内容は,ファイルかディレクトリ,シンボリックリンク,もしくは (p がレプリカの中の何も指し示していない時は) 空っぽであるかもしれません.より詳しく見てみましょう.
- p が普通のファイルを指す場合,p はこのファイルの実際の内容 (つまりバイト列) と,パーミッションを表わすビット列です.
- p がシンボリックリンクを指す場合,p はシンボリックリンクが指し示している先の内容です.
- p がディレクトリを指す場合,p は単なる "DIRECTORY" というトークンと,パーミッションを表わすビット列です.
- p がレプリカの中の何も指していない場合,p は "ABSENT" というトークンになります.
Unison は同期が成功した後,それぞれの path の内容を記憶します*3.
あるレプリカにおいて,path の中身が最後に同期させた時から見て変更されている場合,その path は変更されたと判断します.
衝突
以下のような場合,その path は衝突しているとされます.
- どちらかのレプリカで変更された.
- その path かその子がもう一方のレプリカで変更された.そして
- 2つのレプリカの同一の path の内容が異なる.
衝突の解決
Unison はいくつかの異なった段階を踏みます.
- それぞれのホストにおいて,どの path が変更されたか判断するために,現在のレプリカの内容とアーカイブファイルの内容を比較します.
- 両方のレプリカで変更されていて,なおかつ内容が異なる path (false conflicts) を調べます.これらの path は両方のレプリカにおいて,同期されたと内部的にマークされます.
- 更新された path をユーザに提示します.衝突しない更新に関しては,更新されたレプリカ同様にもう一方を更新するという,デフォルトの動作を提案します.衝突する更新は単に表示されます.ユーザはレプリカ全体の更新状況を見極め,衝突しない更新の動作を変え,衝突する更新に対する動作を決めることができます.
- 選択された動作を一つずつ実行します.転送されたファイルはまず受け取り側のホストに一時ファイルとして作成され,次にそのファイルをあるべき場所に移動します.
- アーカイブファイルに現在のレプリカの内容を反映します.
原則
その実行内容の重要性と繊細さから,シンクロナイザが通常の状態でどのような動作をしているのかだけでなく,システムのクラッシュや通信が切断した場合等の異常事態にどのように動作するのかを知ることもまた重要です.
Unison は実行中,常に内部の状態やレプリカの状態を保護するよう設計されています.特に,以下のような特徴を備えています.
- 双方のレプリカの全ての path は,1)その元の状態 (つまり変更されていない状態) か,2)その正常に更新された状態 (つまりユーザが意図した内容に更新された状態) のいずれかを常に保持しています.
- ディスク上に保存された Unison 内部の情報は常に,1)変更されていない状態か,2)同期に成功した path の情報を反映した状態のいずれかです.
つまり結論として,人為的にであろうと事故であろうと,いつ Unison の実行を停止しても安全だということが言えます.
更新を実行している最中に停止された場合,ある path の更新は完了しているのにアーカイブファイルにその更新が反映されていないということが起こり得ます.しかし問題はありません.次に Unison が実行された際に,Unison はこれらの path が変更されていながらも内容は同じであると判断し,同期は成功したと記憶してその path に関する処理を終了するからです.
Unison が停止された場合,レプリカの中に (.tmp という拡張子の付いた) 一時ファイルが残っていることがあります.それらのファイルは消してしまって構いません.同様に (deprecated な) backup フラグが設定されている場合,Unison は file.0.unison.bak というような古いバージョンのファイルを残します.これらのファイルも,Unison の動作には影響ありませんから,消してしまって結構です.
Unison は,動作しているマシンの間のクロック・スキュー (クロックのばらつき) には影響されません.Unison は単に一つのホスト上で手に入れたタイムスタンプの比較を行ない,それを行なう上で必要な前提は,それぞれのシステムのクロックが常に前に進むということだけだからです.
アーカイブファイルが削除されている (もしくはファイルのフォーマットが変更されていて読み込めない,もしくはある root に対して初めて実行したためまだファイルが作られていない) 場合,Unison は非常に保守的な動作をします.つまり双方のレプリカが最後の更新時に完全に空であったかのように動作します.その結果,初めての実行時には一方のレプリカに存在するファイルは他方に転送され,両方のレプリカに存在しながら内容が異なるファイルは衝突しているとマークされます.
あるファイルに対して変更を加えずに更新時刻だけを変更する (touch する) 操作は,Unison の動作に影響を与えません.Unix では,Unison はどのファイルが絶対に更新されていないかを知るために,まずファイルの更新時刻を調べます.そして更新された可能性のあるファイルに対してフィンガープリントを計算し,最後の更新時の状態と比較します.
アーカイブファイルを両方のレプリカから削除して,Unison を洗脳しても構いません.次に実行した時,Unison はレプリカの全てのファイルが新しく作られたものだと仮定します.
Unison の実行の最中にファイルに変更を加えても安全です.古い状態で更新してしまった時,もしくは更新している最中にターゲットのレプリカのファイルが変更された時は,Unison はそのファイルの更新に失敗した旨を表示します.最新の更新を行なうにはもう一度 Unison を実行してください.
UIからの (例えば i キー等による) 無視 (ignore) パターンの変更は,すぐに現在のプロファイルに反映されます.
警告と短所
Unison を利用する際に注意すべきことがあります.バグの完全なリストは,ソースアーカイブの中の BUGS.txt にあります.
- 高速化のため, (実行する OS のアーキテクチャにもよりますが) 変更検知アルゴリズムは実際には近似的な方法を用いることがあります.
- 特に Unix における実装では,ファイルの実際の内容と前回の記録とを比べるのではなく,ファイルの inode 番号と更新時刻のみをチェックしています.どちらも変更されていなければ,そのファイルは変更されていないという結論に達します.
- 一般的な状況では,この方法は変更を見誤ることがあっても,本当の更新を見逃さないという点で安全です.しかし,retouch 等を使ってファイルの更新時刻を巻き戻し,Unison を騙すことは可能です.
- 自分専用のファイルシステムと共有のサーバの間でファイルを同期させる場合,パーミッションに気をつける必要があります.Unison はデフォルトではパーミッションもそのまま同期させるので,グループに書き込み権限を残したまま同期させてしまうと,他のユーザに上書きされてしまう可能性があります.
- 両方のマシンで umask を 022 などに設定してこの問題を回避することができます.
- GUI は今のところシングルスレッドで動いています.これは Unison が時間の掛かる処理を行なっている時,その処理が終了するまで画面が書き換わらないということを意味します.Unison が何らかの動作している間,GUI 画面に触らないようにすることをお薦めします.
- Unison は今のところハードリンクを理解しません.
*1 但しこの方法は,ホスト間が十分に速い回線で接続されている場合に限った方が良いでしょう.更新を検知するために,リモートマシンのレプリカがローカルマシンに転送される必要があるからです.
*2 例えば Windows マシンの c:\pierce と Unix サーバの ssh://saul.cis.upenn.edu/home/bcpierce の同期を取る場合,current/todo.txt という path はクライアントでは c:\pierce\current\todo.txt となり,サーバでは /home/bcpierce/current/todo.txt となります.
*3 つまり2つのレプリカの内容が同じであったときの最後の状態を記憶しているわけです.