rsync といえば、ファイル同期の定番ツールです。
「手元のファイルをサーバーに送る」「差分だけ転送する」「バックアップを効率よく取る」など、地味だけど超重要な仕事をずっとこなしてきました。
そんな rsync を、BSDライセンスでゼロから実装したものが openrsync です。
ここで大事なのは、単なる“rsyncのコピー”ではなく、別実装だという点です。こういうプロジェクトは、互換性の検証、実装の学習、ライセンス上の選択肢を広げる、という意味でかなり価値があります。個人的には、こういう「よく使う道具を別の思想で作り直す」試みはかなり好きです。中身が見えるからです。
README によると、openrsync はOpenBSD 版がベースで、そこにポータビリティ向けの“glue”が足されているとのこと。しかも現在は OpenBSD base に統合済みで、今後の改善は tech@openbsd.org にパッチを送ってほしい、という案内になっています。
つまり、GitHub 上のこのリポジトリは「生きた実装」ではあるものの、本流は OpenBSD 側にある、という理解がよさそうです。
openrsync は、modern rsync と互換性があると説明されています。
ただし、互換といっても何でも同じではなく、rsync のコマンドライン引数は一部のみ対応です。
README では、テストに rsync 3.1.3 を使っているが、protocol 27 をサポートする相手ならよいと書かれています。
このへんは少し玄人向けですが、要するに「古すぎない rsync となら会話できる」という感覚でよさそうです。
また、公式にサポートされる OS は OpenBSD。
でも、README によれば 他の UNIX 系でもコンパイル・実行できるとのことです。
この“OpenBSD 主導だけど他でも動く”感じは、OpenBSD 系プロジェクトらしい潔さがあって好感が持てます。
README にあるインストール手順はかなりシンプルです。
./configure
make
make install
アンインストールも make uninstall でできます。
こういう「Unix の王道」みたいな作法は、今どきの大規模ビルドシステムに慣れた目には逆に安心感があります。派手さはないけど、道具として信頼しやすい。
しかも、通常の rsync と共存しても衝突しないと明記されています。
これは地味ですが大事です。実運用では「置き換え」よりも「併存」が多いので、ここが明言されているのはありがたいです。
README の一番おもしろい部分は、rsync のアルゴリズム説明です。
rsync の魅力は、ざっくり言えば「全部送り直さず、必要なところだけ送る」こと。これにより、ネットワーク転送量を抑えられます。
流れをかなり噛み砕くと、こうです。
この仕組みが、rsync を rsync たらしめる中核です。
ファイルまるごとではなく、**“ブロック”**という小さな塊で見比べるのがミソです。ブロックとは、ファイルを一定サイズに切った断片のことだと思えばOKです。
README では、rsync アルゴリズムを次の2つに分けています。
実装上もそれぞれが別ファイルに分かれています。
sender.creceiver.cこういう分業は、読みやすさの面でも意味があります。
同期ツールって一見単純そうに見えるのに、実は「送る側」「受け取る側」「ファイル一覧」「比較」「ハッシュ」「ソケット通信」など、仕事がかなり多いんですよね。なので、責務が分かれているのはかなり健全だと思います。
rsync の面白さの一つは、ファイル一覧(file list)を先に共有することです。
この一覧には、名前だけでなく、mode や mtime などのメタデータも含まれます。
受信側と送信側は、この一覧をもとに、同じ順序でファイルを扱えるようになります。
しかも、一覧は単純な順番ではなく、辞書順でソートされます。さらに、ディレクトリが先に処理されるような順序になっているとのことです。
ディレクトリを先に作ってから、その中身を置く。これは当たり前に見えて、実装ではかなり大事です。
個人的には、この「見た目は地味だけど、順序設計が全体を支えている」感じが rsync らしくて好きです。派手なUIがないぶん、アルゴリズムの上品さが前に出ます。
通常ファイルの流れは、ざっくり次の通りです。
ファイルサイズと最終更新時刻が同じなら、すでに最新とみなして更新要求をしません。
ファイルを一定サイズのブロックに区切ります。
ファイルが端数になれば、最後のブロックは小さくなります。
README では、各ブロックに対して
の2段階を使うと説明されています。
ハッシュとは、データの“指紋”みたいなものです。
同じ内容なら同じ値になり、違う内容なら違う値になりやすい。
まず軽い計算で候補を絞り、最後により厳密な確認をする、という二段構えです。これ、実装としてかなり賢いです。全部を重く検査するより、ずっと効率がいい。
送信側はソースファイルを走査し、受信側から届いたブロック情報と照合します。
一致した部分は再送せず、一致しない差分だけ送る。
受信側は、届いた生データと一致ブロックを組み合わせてファイルを復元します。
この仕組みのおかげで、たとえばファイルの一部分だけが変わった場合に、全体を送り直さなくて済むわけです。
ネットワーク越しの同期で rsync が強い理由は、まさにここにあります。
README では、ファイル種別ごとに処理が分かれることも説明されています。
シンボリックリンクやディレクトリは、普通のファイルとは性質が違います。
だからこそ、同じロジックに押し込まず、きちんと分けているのは実装として正しいです。こういう細かい気配りが、ツールの“気持ちよさ”につながるんですよね。
README には、openrsync の正式なドキュメントは manual pages だとはっきり書かれています。
openrsync(1)rsync(5)rsyncd(5)つまり、README はあくまで導入で、詳細は man page を見てね、というスタンスです。
これは Unix 文化の王道でもありますし、個人的にはかなり好きです。GitHub の README を万能ドキュメントにしないのは、ある意味で誠実だと思います。
openrsync の面白さは、単に「rsync の別版」があることではありません。
むしろ、
このあたりが魅力です。
特に、README で「canonical documentation は man page」と言い切っているのが好印象でした。
派手な宣伝より、実務でどう使うか・どう実装されているかを重視している感じがします。
こういうプロジェクトは、表向きは地味でも、技術的にはかなりおいしい。
rsync を“なんとなく便利なコマンド”で終わらせたくない人には、読む価値があると思います。
openrsync は、rsync の仕組みを BSD 系の世界で再実装した、堅実で学びが多いプロジェクトです。
OpenBSD を軸にしつつ、他の UNIX でも動くよう配慮されていて、アルゴリズムの説明も丁寧。
「差分同期って結局どうやってるの?」という疑問に、かなり真面目に答えてくれる実装だと思います。
参考: GitHub - kristapsdz/openrsync: BSD-licensed implementation of rsync