1024 文字
5 分
rsyncのappendオプションのせいでファイルが壊れたり転送されない件について
2020-01-18
2020-03-08

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

現象#

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

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

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

Terminal window
$ cat src/hoge.txt
hogehoge
$ cat dst/hoge.txt
fugafuga

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

Terminal window
$ rsync -a --append src/ dst/

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

Terminal window
$ cat dst/hoge.txt
fugafuga

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

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

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

Terminal window
$ cat src/hoge.txt
hogehoge
$ cat dst/hoge.txt
fugafuga
// 何も表示されない
$ ls dst2/

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

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

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

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

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

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

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

Terminal window
$ cat src/hoge.txt
hogeeeeeee
$ cat dst/hoge.txt
fugafuga

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

Terminal window
$ rsync -a --append src/ dst/

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

Terminal window
$ cat dst/hoge.txt
fugafugaee

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

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

原因#

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

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

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

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

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

なので、

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

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