rsyncのappendオプションのせいでファイルが壊れたり転送されない件について

データのバックアップにrsyncを使ってみたのですが、appendオプションをつけたせいでファイルが壊れたり転送されなかったりしてはまったので、もうはまらないように備忘録を残しておきます。

現象

rsyncでファイルの同期をとろうと思ったのですが、一部ファイルが転送されなかったり壊れたりしました。

差分があるのにファイルが更新されないパターン

まずは差分があるのにファイルが更新されないパターンです。以下のようなファイルがあって、src/以下のファイルをdst/に転送したいです。

$ cat src/hoge.txt 
hogehoge

$ cat dst/hoge.txt 
fugafuga

この場合、append付きのrsyncのコマンドは以下のようになります。期待としては、src/hoge.txtdst/hoge.txtが同じ内容になっていてほしいです。

$ rsync -a --append src/ dst/

実行してみました。dst/hoge.txtの内容は更新されませんでした。

$ cat dst/hoge.txt 
fugafuga

いろいろ試したところ転送前の状態が、src/hoge.txtのファイルサイズdst/hoge.txtのファイルサイズの場合、差分があっても更新されないみたいです。

そもそもファイルが転送されないパターン

差分バックアップをしたかったので、上のコマンドにlink-destオプションも追加してみました。ファイルは以下のようになっています。link-destにはdst/を指定します。

$ cat src/hoge.txt 
hogehoge

$ cat dst/hoge.txt 
fugafuga

// 何も表示されない
$ ls dst2/

この場合、rsyncのコマンドは以下のようになります。期待としては、新しくdst2/hoge.txtが作成されていてほしいです。

$ rsync -a --append --link-dest=`pwd`/dst/ src/ dst2/

実行してみました。dst2/以下には何も転送されていません。

// 何も表示されない
$ ls dst2/

先ほど同様、転送前の状態がsrc/hoge.txtのファイルサイズdst/hoge.txtのファイルサイズの場合、差分があっても更新されないみたいです。

ファイルが壊れるパターン

次はappendオプションをつけてファイルが壊れるパターンです。以下のようなファイルがあります。これをappendオプションをつけてrsyncで転送してみます。

$ cat src/hoge.txt
hogeeeeeee

$ cat dst/hoge.txt 
fugafuga

rsyncコマンドは以下です。src/hoge.txtの内容がdst/hoge.txtに反映されていてほしいです。

$ rsync -a --append src/ dst/

実行してみました。dst/hoge.txtが2つのファイルが混ざったようなおかしなことになりました。

$ cat dst/hoge.txt 
fugafugaee

諸々試してみた感じ、転送前の状態で次の2つの条件を満たすとこの事象は発生しました。

  • src/hoge.txtのファイルサイズ<dst/hoge.txtのファイルサイズ
  • src/hoge.txtdst/hoge.txtの先頭数バイトの内容が異なる

原因

rsyncについて調べたときに、途中で中断・再開するためにはappendオプションをつけておけ、みたいな記事を見かけたので何も考えずにつけたのですが、このappendオプションが悪さをしていたみたいです。

manコマンドでappendオプションの意味を調べてみます。

$ man rsync
...
     --append                append data onto shorter files
...

今まで試したrsyncの挙動と一緒に考えると、どうやら転送先ファイルの方がサイズが小さい場合に、サイズの違い分の差分のみを転送先ファイルに追加しようとするようです。

つまり今回のファイルが壊れるケースだと、ファイルサイズの差分分の末尾のeeだけ転送しようとしたようです。しかし、実際には末尾ee以外にも差分があったため、実行結果が2種類のファイルの内容が混ざったようなおかしなことになったようです。

なので、

  • 転送元ファイルよりも転送先ファイルの方がサイズが小さい場合 → ファイルを転送しない
  • 転送元ファイルと転送先ファイルにサイズの違い分以上の差分がある場合 → 転送元と転送先ファイル内容が混ざる

といった状態になるみたいです。

コメント