Logo address

cpdir : a backup tool for Plan9

目次

2002/08/28
2009/08/22 (追加)
2009/10/10 (追加)

Plan9 用のバックアップツールを作成したので紹介する。
このようなツールを作成したのは、筆者の経験から mkfs では不十分であることが分かったからである。Plan9 第2版では主ファイルシステムがクラッシュした事が無かったのであるが、第3版では何回かクラッシュした。(これは多分ベル研の責任ではないであろう。これにパッチを充てた idefs がまだ不安定だったのでは思われる。)
しかし、どんなに完全なものでも壊れる事がある。そして壊れて見た時に何が問題であったかがわかる。筆者は mkfs でバックアップを採っていたのであるが、mkfs は完全な写しを作らないのである。特に、ファイルが既にバックアップ先に存在していた時に、アクセスモードなどを合わせない。owener の変更があったときにもそうである。
消されたファイルはバックアップ先にそのまま残される。

こうした訳で、信頼性と効率のバランスをとったバックアップツールを作成した。
この最初の版が backup である。
backup を作ってみると、これがディレクトリのコピーや、ディレクトリのバックアップに使える事がわかった。そして backup を廃止して、cpdir に変更した。


注: cpdir ver.1.7 に関する説明が http://plan9.aichi-u.ac.jp/cpdir/ にあります。合わせて読んで下さい。(2009/08/22)


cpdir の使い方

foo を既に存在するディレクトリとせよ。bar はまだ存在しないとせよ。その下で、
	term% cpdir foo bar
を実行すると、foo のコピーが bar にできる。この場合、ファイルの修正日が保存される。
bar が既に存在する場合には
	term% cpdir -m foo bar
である。-m はマージオプションである。bar があればマージに決まっているからいらないのでは…とも考えられようが、マージは危険な作業である。従ってその事を自覚して貰うために -m オプションを要求する事とした。
foo の中の幾つかのファイルを修正し、あるいはいくつかを foo に追加し、cpdir を実行してみればわかるように、cpdir は変更されていないファイルのコピーを行わない。

マージを巡る諸問題に関する考察は後回しにする事とし、まずは cpdir のオプションを紹介する事とする。

term% cpdir
cpdir: usage: cpdir [-mugvR] [-l file] {-x file} srcdir dstdir [path ....]
-m: マージ
-u: オーナーをコピー元に合わせる。(可能ならば)
-g: グループをコピー元に合わせる。(可能ならば)
-v: verbose (メッセージをくどくどと出力させる
-R: コピー元に存在しないコピー先のファイルを消す
-l file: コピーするファイルやディレクトリの一覧を与える
-x file:  コピーしないファイルやディレクトリのパターンの一覧を与える
srcdir: コピー元のディレクトリ
dstdir: コピー先のディレクトリ
path ... : srcdir 内のコピーするファイルとディレクトリ


注意: -x option は ver.1.5 で廃止されています。


cpdir を使ったファイルシステムのバックアップ

Plan9 システムでのファイルシステムは UNIX 等に比べると非常にシンプルである。
仮想的な名前空間とデバイスが提供する名前空間がきれいに分離されており、しかも
後者にはリンクが存在しない。
デバイスが提供する名前空間を Plan9 にの習慣に従って
	/n/9fs
	/n/kfs
としよう。
Plan9 のバックアッププログラムの目標は /n/9fs の完全なコピーを効率よく /n/kfs に作成する事になる。

Plan9 には mkfs が存在し、バックアップにある程度使えるが次の欠陥を持っている。

  1. /n/9fs で削除されたファイルやディレクトリを /n/kfs から削除しない。
  2. /n/9fs で変更されたパーミッションやグループ、オーナー情報を /n/kfs で変更しない。
筆者のツール(cpdir)はこうした問題を解消し、効率よくバックアップを採ることを目指している。

バックアップをとるディレクトリは cpdir の引数として与えてもよいが -x オプションによってファイルの中に一覧を書くこともできる。
後者の場合にはファイルは例えば次のように書く。

# each line is trimmed before evaluation
# lines starting with `#'  are comments
# one path per line
386
cron
dist
rc
lib
sys
lp
acme
mail/lib
adm
dist
usr
コピーしないファイルやディレクトリパターンの一覧を -x オプションによって与えることができる。例えば次のように書く。
adm/users
*/tmp/*
*/_*
ここにおける * は、シェルにおけるパターンマッチングと似ているが、次の点で異なる。すなわち、
* はディレクトリ区切り子である / にもマッチする。従って
	*/tmp/*

	/usr/arisawa/tmp/*
だけではなく
	/usr/arisawa/tmp/T/foo
などにもマッチする。

cpdir は当然 Plan9 のアクセス制限の影響を受ける。
/n/9fs がファイルサーバであれば、アクセス制限を回避するよい手段は存在しない。
(バックアップ中にシステムの運用を止めたいとは誰も思わないであろう。)
他方 /n/kfs の方は kfs のオーナー(hostowner)であればアクセス制限を無効にでき、オーナー情報を含めて自由に設定できる。
従って cpdir は基本的にはサーバのオーナーである bootes が実行することによって有効に機能する。
エンドユーザは bootes が読み取れない /n/9fs のファイルのバックアップをとる必要がある。そのようなファイルとしては例えば

	/mail/box/arisawa
などがある。

マージを巡る問題

マージの場合に、コピー元とコピー先に同じ名前があれば cpdir とどのように振る舞うか?
Time(src) と Time(dst) で各々コピー元とコピー先の名前が作成された時刻としよう。
この場合には src や dst が DIR(ディレクトリ) か FILE(ファイル) かによって以下のように動作が異なる。
CASE: Time(src)<Time(dst)
	src	dst
	DIR	DIR	# さらに下位のディレクトリを調べる
	DIR	FILE	# なにもしない
	FILE	DIR	# なにもしない
	FILE	FILE	# なにもしない
CASE: Time(src)>Time(dst)
	src	dst
	DIR	DIR	# さらに下位のディレクトリを調べる
	DIR	FILE	# dst を src に合わせる
	FILE	DIR	# dst を src に合わせる
	FILE	FILE	# dst を src に合わせる
CASE: Time(src) = Time(dst)
	src	dst
	DIR	DIR	# さらに下位のディレクトリを調べる
	DIR	FILE	# dstの fstat を srcの fstat に合わせる
	FILE	DIR	# dstの fstat を srcの fstat に合わせる
	FILE	FILE	# dstの fstat を srcの fstat に合わせる
ここに fstat と変更時刻情報やファイルパーミッションなどである。

cpdir の目標はコピー元の情報をコピー先に反映させる事である。cpdir はファイルシステムのバックアップツールとして生まれたのだから、コピー元を優先している。しかしながら、コピー先のディレクトリが一挙に削除される事もあるので注意して使用すべきであろう。

cpdir はどこに?

cpdir
http://plan9.aichi-u.ac.jp/netlib/cmd/
に置かれている。

バグを見つけたら、あるいは改善の提案があれば
arisawa@aichi-u.ac.jp
にメールで知らせてほしい。