Ubuntuでバックアップが失敗する話、あるいはディスクサイズとファイルサイズについて
κeenです。寝れないので小ネタを。数年悩んでた問題がようやく解決しましたのでそれについて。
経緯
30GBくらいのファイルのバックアップをdejadupを使って500GBのHDDに取ろうと思ったらディスクの空き領域がないって言われるんだけど何が原因なんだろう。因みにホストのSSDも500GBある。Ubuntu 16.04と16.10で起きた。
— κeen (@blackenedgold) 2016年12月3日
Ubuntuのバックアップがとれない病に掛かってるんだけどこの度17.04に上げてもダメだった。因みにバックアップデータ数十GBに対してバックアップ先は500GBと十分にある。 pic.twitter.com/vgSE8uoLtB
— κeen (@blackenedgold) 2017年4月18日
エラーメッセージの情報量が少ないので打てる手が少ないですね…。
このあとバックアップ用のHDDを買い替えて2TBのものを用意しましたがダメでした。 ハードの問題ではないと判明したのでUbuntuのバックアップ(ソフトウェア名はdeja-dup)のバグを疑い、しばらく放置することにしました。 流石に再現条件を割り出せてないので自らバグレポートをすることはせず、熱心な他人に委ねようという判断です。
原因究明
最初に問題が発生してから2年くらいになりますがふと思い立って少しずつバックアップを取ったらどうかと試し始めます。
ubuntuのdejadupがバックアップに失敗する問題、ちょっとずつやれば成功するな。どこのサイズが足りてないんだろう。
— κeen (@blackenedgold) 2018年4月26日
少し進展しましたね。
さらにここでデバッグする気力が湧いたので色々試し始めます。
top
でCPU Usageをみてるとdeja-dupはただのフロントエンドでバックアップをしているのはduplicityということに気づきます。
そこで ps aux
でコマンド引数を抜き出して自分の手でduplicityを操作し始めます。
とりあえずduplicity叩いたらエラーメッセージは見えた。150Gくらいのバックアップに4TB必要と言っている。ほんまか?
— κeen (@blackenedgold) 2018年4月27日
150Gというのは du ~/
で測ったものです。そもそもUbuntuをインストールしているディスク全体でも500GBなので何か設定を間違っていたとしても流石に500GBには収まる筈。バックアップのメタデータでちょっと嵩むとしてもこれはおかしいですね。
さらにこのあと --dry-run
ではなく実際にコピーを走らせてみると、とあるファイルでずっと止まってることに気づきます。
理解した。pijulのdbファイルが中身はほぼ空だけどサイズ上4TBあることになってた。
— κeen (@blackenedgold) 2018年4月27日
ということで犯人がわかりました。余談ですがpijulというのは新興バージョン管理システムの1つです。このファイルはpijulがバージョン0.1くらいのときに作ったもののようでした。その時のpijulはメタデータDBにひとまずでかいファイルを作るようになってたんですね。
ということでこのファイルを消して無事バックアップを取れました。
しかし4TBのファイルを作っているのに du
は 150GBと報告しました。これはどういうことなのでしょうか。これが今日のお話。
ディスク上のサイズとファイルサイズ
du
のマニュアルを見ると、 du
は ディスク上のサイズ 、いわば物理サイズを見積もるツールだと言っています。一方 ls
などでみるのは ファイルサイズ 、論理的なサイズです。
両者に違いがあるかというと、スパースファイルの場合実際のディスクサイズはずっと小さくなります。
Linuxだと0ページ最適化してくれるから4TBあってもディスクスペースは食わないんだけどそれをtarにすると4TBのtarが出来上がるんだろうか。
— κeen (@blackenedgold) 2018年4月27日
ということで実験しましょう(終わった後で上のArch Wikiに全部書いてることに気づきましたが気にしない)。tarが出てきたのはduplicityがフォーマットとしてtarを用いているからです。
truncate
コマンドでファイルを無意味に伸ばすことができます(普段はファイルをサイズ0に切り詰めるコマンドですね:) )
$ truncate -s10M file
さて、これを du
と ls -l
で確認してみましょう。
$ ls -lh file
-rw-r--r-- 1 kim kim 10M 4月 28 02:59 file
$ du -h
4.0K .
見かけ上のサイズと実際のサイズが異なっていますね。これをtarballにしてみましょう。
$ tar cf file.tar file
$ ls -lh
合計 11M
-rw-r--r-- 1 kim kim 10M 4月 28 02:59 file
-rw-r--r-- 1 kim kim 11M 4月 28 03:00 file.tar
$ du -h
11M .
tarballにすると本来のサイズに膨らむことがわかりました。
そしてArch Wikiによると tar
はオプションでsparse fileを扱えるようなのでそれも実験してみましょう。
$ rm file.tar
$ tar Scf file.tar file
$ ls -lh
合計 11M
-rw-r--r-- 1 kim kim 11M 4月 28 03:00 --sparse
-rw-r--r-- 1 kim kim 10M 4月 28 02:59 file
-rw-r--r-- 1 kim kim 10K 4月 28 03:01 file.tar
$ du -h
16K .
本当に小さくなってますね。
まとめ
- ext4などのファイルシステムはsparse fileを効率的に保存してるよ
- duがデフォルト表示するのはディスク上のサイズであってファイルサイズではないよ
- sparse fileを上手く扱えないとバックアップが元のディスクサイズより巨大になることがあるよ