« "YouTube Object Code" を IE6 多応にしました | Main | 左腕の疲労感 »
ローカルディスクから iDisk への一方向の同期、つまり同期というよりも反映ですが、このブログのそれに rsync を使わないことにしました。MobileMe になってから途中で iDisk が反応しなくなるようになったからです。
このブログもそうですが、MobileMe の機能を使わずに iDisk 上の web スペースに直接自分でサイトを作るときに、一旦ローカルに作りローカルの web サーバでプレビューしてから iDisk へ反映させています。その反映の道具として rsync を使っていました。
rsync を使う長所は、変更や追加されたもののみが iDisk に転送されることと削除されたものもきちんと反映してくれることです。短所も有ります。反映元であるローカルディスクのあるディレクトリと反映先の iDisk 上のあるディレクトリを比較して反映するのですが、その際に iDisk 上のそのディレクトリ以下をくまなく調査するのです。このブログを例にとると、現在のファイル数はおよそ 1300、ディレクトリ数はおよそ 130 です。そしてディレクトリの深さは最大 4 です。どんなファイルがあって最終更新日やその内容を比較するのですから、iDisk の中を上に行ったり下に行ったり結構右往左往しなければなりません。iDisk はリモートにあるのですからこれは相当通信コストがかかります。つまり、rsync を使う短所は実際に反映を始めるまでの間にかなり通信をして時間がかかるということです。Mac OS X の Finder でアクセスする WebDAV クライアントは結構効率悪い作りになっているようですからこの時間は馬鹿になりません。
それでもうまく機能していたので我慢して rsync を使っていました。MobileMe が .Mac というサービスだったときまでは。
しかし MobileMe になってからしばしば rsync が実際に反映を始めはするのですが、途中で止まるようになってしまいました。iDisk が途中で応答しなくなるのです。Finder からのアクセスはある程度キャッシュが効いているのでできるように見えますが、rsync が触っていないディレクトリを表示させようとすると Finder も固まります。iDisk が応答してこない証拠です。特に Thingamablog の都合で全ページが更新されたときは悲惨です。Mac OS X を強制リブートして反映を再開しても少し反映しては iDisk が無応答になる、そして再び強制リブート、そういうプロセスを 12 時間以上繰り返してもすべてを反映できないのです。それはちょうど一ヶ月以上このブログを休んでいていざ再開しようとしたときのことでした。
途中の睡眠も入れて 30 時間程度経ち、とうとう業を煮やしました。もうブログの更新に rsync は使わないことにしようと。そして iDisk のアクセスを必要最小限にするためにシェルスクリプトを作りました。.Mac (というかその前身の iTools) の頃にそういう目的の perl スクリプトを作ったことがあったのですが、それよりもアクセスを少なくするのが目標です。
この目標のために rsync でできていた削除の反映を捨てました。記事を削除することはまず無いので Thingamablog でコンテンツを作成している限り削除は殆ど発生しないからです。
次は実際に使っているスクリプトから当該部分を抜粋してテンプレートにしたものです。削除の反映が不要で、ローカル iDisk を使っておらず、iDisk へのアクセスではマウントしている場合に使えます。
#!/bin/sh
LocalBaseDir='ここに反映元のディレクトリを入れる(最後に / は要らない)'
RemoteBaseDir='ここに反映先のマウントされたディレクトリを入れる(最後に / は要らない)'
# デバッグやお試し実行時は次の行の行頭に # を挿入
Debug=
# デバッグやお試し実行時は次の行の行頭の # を削除
#Debug=echo
#( # 実行の様子をコンソールに吐き出すときは行頭の # を削除
if cd "${LocalBaseDir}"; then
if [ -f .published ]; then
Published=false
ErrorHasOccuerd=false
for target in `find * -newer .published`
do
remoteTarget="${RemoteBaseDir}/${target}"
if [ -d "${target}" ]; then
if [ ! -d "${remoteTarget}" ]; then
if ${Debug} mkdir -v "${remoteTarget}"; then
Published=true
else
ErrorHasOccuerd=true
fi
fi
elif [ -f "${target}" ]; then
if ${Debug} cp -v "${target}" "${remoteTarget}"; then
Published=true
else
ErrorHasOccuerd=true
fi
fi
done
if [ ${ErrorHasOccuerd} = 'false' -a ${Published} = 'true' ]; then
${Debug} mv .published .published.old
${Debug} touch .published
fi
else
if ${Debug} cp -rv * "${RemoteBaseDir}/"; then
${Debug} touch .published
fi
fi
fi
#) 2>&1 | logger # 実行の様子をコンソールに吐き出すときは行頭の # を削除このスクリプトには次の制約があります。
これを回避するのはシェルスクリプトではしんどいので perl スクリプトか何かにするといいでしょう。
「iDisk が応答しない」と表現しましたが、iDisk のサーバが応答しないのではなく Mac OS X の WebDAV をマウントする役割を担っている部分が応答しなくなるのだと思います。