rsyncの悩み

ディレクトリの同期とくればrsyncが定番でありオンリーワンと言えよう。

ただこのrsync、久しぶりに使うとコマンド書式を忘れてて苦労するのですよ。
「確かオプションは-avzだったかな」「リモートホストの指定方法はなんだっけ・・・」とmanとしばらく格闘するわけですな。

ディレクトリ指定の複雑さ

加えてディレクトリの指定の仕方も理解しにくい。

例えば、二つのディレクトリを同期させたいとき。
rsync -avz dirA dirBを実行すると、こんなことが起こる(確かこうだった…。スラッシュがあるかないかで違ったかも)。

  • dirBがないとき
    →dirBが作られる。
  • すでにdirBがあるとき
    →dirB/dirAが作られる。

前者をイメージしていたのに、後者のパターンにゲンナリすることがよくある。
そこで使えるのがcpdupである。

お手軽ミラーユーティリティcpdup

cpdupはファイルシステムのミラーを作るユーティリティである。
「ファイルシステムの」と書いたのは、ハードリンク、ソフトリンク、デバイス、パーミッションなども面倒見てくれるからである。

リモートホストと同期させる場合のプロトコルにはsshが使われる。
また、リモートホストにもインストールが必要。

rsyncの代替にはならないけれども、手軽で、わかりやすいインタフェースを持つ。

manはこちら。
http://linux.die.net/man/1/cpdup

cpdupのインストール

FreeBSDだと、portsならsysutils/cpdup。pkgでもOK。
Linuxでもパッケージから手に入るでしょう。
リモートと同期させる場合には、リモートホストにもcpdup入れておくこと。

cpdup書式

書式は以下の通り。
オプションは一部。全部見たいならmanでどうぞ。

cpdup [-C] [-v[v]] [-d] [-I] [-i0] [-o] [-q] <ソースDir> <tターゲットDir>

通常的に使うオプションは、「-C -vv -d -I]でよいと思う。

-C    リモートホストとファイル送受をするとき、sshコネクションを圧縮する。
-vv   処理状況を表示させる。v一つだと変更のあったときしかメッセージが表示されないので、v二つがよい。
-d    処理の行われるディレクトリを表示させる。
-I    処理が終わったあとにサマリを表示させる。
-i0   確認せずにファイルやディレクトリを削除する。
-o    削除を一切しない。追加か上書きのみ。
-q    表示をさせない。

cpdup実行例

まず手元にファイルを含むディレクトリを作る。
下記の例ではtestDirディレクトリに、a, b, c, d, e, fというファイルを作った。

$ mkdir testDir
$ cd testDir/
$ touch a b c d e f
$ ls
a       b       c       d       e       f
$ cd ..

典型例

ではこれをcpdupしてみよう。
リモートの192.168.154.241にコピーする。
基本の「-C -vv -d -I」で。
出力がとても分かりやすい。

$ cpdup -C -vv -d -I ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
~/testDir
Scanning ./testDir ...
~/testDir/f                      copy-ok
~/testDir/a                      copy-ok
~/testDir/e                      copy-ok
~/testDir/b                      copy-ok
~/testDir/c                      copy-ok
~/testDir/d                      copy-ok
cpdup completed successfully
0 bytes source, 0 src bytes read, 0 tgt bytes read
0 bytes written (nanX speedup)
6 source items, 6 items copied, 0 items linked, 0 things deleted
2.5 seconds     0 Kbytes/sec synced     0 Kbytes/sec scanned

ターゲットにすでにディレクトリがあってもOK.

そこでもう一度同じコマンドを実行してみる。
何もコピーされない。
これがもしrsyncだと、testDir/testDirが作られることになる。

$ cpdup -C -vv -d -I ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
~/testDir
Scanning ./testDir ...
cpdup completed successfully
0 bytes source, 0 src bytes read, 0 tgt bytes read
0 bytes written (nanX speedup)
6 source items, 0 items copied, 0 items linked, 0 things deleted
2.6 seconds     0 Kbytes/sec synced     0 Kbytes/sec scanned

ターゲットのファイルを削除するときは確認あり。

では手元の./testDir/aを削除してもう一度。
ターゲットのtestDir/aを削除するか、聞いてくれる。

$ rm ./testDir/a

$ cpdup -C -vv -d -I ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
~/testDir
Scanning ./testDir ...
remove ~/testDir/a (Yes/No) [No]? yes
cpdup completed successfully
0 bytes source, 0 src bytes read, 0 tgt bytes read
0 bytes written (nanX speedup)
5 source items, 0 items copied, 0 items linked, 1 things deleted
4.3 seconds     0 Kbytes/sec synced     0 Kbytes/sec scanned

-i0で削除時の確認を抑制

今度は手元の./testDir/bを削除し、-i0を付けてみる。
確認なくターゲットのbを削除している。

$ rm ./testDir/b
$
$ cpdup -C -vv -d -I -i0 ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
~/testDir
Scanning ./testDir ...
~/testDir/b                      remove-ok
cpdup completed successfully
0 bytes source, 0 src bytes read, 0 tgt bytes read
0 bytes written (nanX speedup)
4 source items, 0 items copied, 0 items linked, 1 things deleted
2.6 seconds     0 Kbytes/sec synced     0 Kbytes/sec scanned

-oでターゲットの削除を抑制

さらに手元の./testDir/cを削除し、-oを付けてみる。
ターゲットのcの削除はされない。

$ rm ./testDir/c
$
$ cpdup -C -vv -d -I -o ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
~/testDir
Scanning ./testDir ...
~/testDir/c                      not-removed
cpdup completed successfully
0 bytes source, 0 src bytes read, 0 tgt bytes read
0 bytes written (nanX speedup)
3 source items, 0 items copied, 0 items linked, 0 things deleted
2.6 seconds     0 Kbytes/sec synced     0 Kbytes/sec scanned

メッセージの抑制

メッセージ表示のオプションをすべて外してみる。
出力がかなり減った。

$ cpdup -C -o ./testDir 192.168.154.241:~/testDir
Password:
Handshaked with cal01
$

さらに-qを付けてみる。
出力が一切ない。

$ cpdup -C -q -o ./testDir 192.168.154.241:~/testDir
Password:
$

たいへん結構。ではスピードは?

rsyncとどれくらい違うか、実験してみた。

FreeBSD 9.2-RELEASEのソースをミラーリングしてみた。
5696のディレクトリに52315のファイルがあり、サイズは800MBである。

ハードウェアのスペックは割愛。
Windows上のVMがソース、古いDELLマシンがターゲットなので…。

rsyncには-avzを、cpdupには-C -vv -d -Iを与えた。

結果。

rsyncは6分。

sent 191011733 bytes  received 1016783 bytes  518295.59 bytes/sec
total size is 686599114  speedup is 3.58

real    6m10.328s
user    0m38.497s
sys     0m33.395s

cpdupは30分。
…30分!?

686599114 bytes source, 686599114 src bytes read, 0 tgt bytes read
686599114 bytes written (1.0X speedup)
52315 source items, 58011 items copied, 0 items linked, 0 things deleted
1893.2 seconds   708 Kbytes/sec synced   354 Kbytes/sec scanned

real    31m33.236s
user    0m8.380s
sys     0m16.133s

ま、まあ、スピードの点では、cpdupはまったく話にならないですな…。
(転送量を見るとcpdupの方はspeedupがあまり効いてないように見えるなあ。)

ミラーリングとは言っても、初回のフルコピーだから、差分コピーだとまた違った結果が得られるかもしれない。
ただちょっとここまで差があると試す気にもなりまへん。

まとめ

cpdupはちょっとしたミラーリングの時に使うには、手軽で書式もわかりやすいので有用、いっぽう、気合い入れてやるミラーリングはrsyncで、って事でいいんじゃないでしょうかね。