目次
はじめに
普段使いのラップトップは Arch Linux で動いていて、主にプログラミングや学校の課題などに使っています。
というかデスクトップ PC を持っていないので、 PC 上で行う作業は全てこのラップトップでやっています。
一年程前までは Timeshift で定期的にシステムバックアップを取っていたのですが、最近は面倒になってずっとバックアップを取っておらず、 OS や PC が壊れて書きかけの課題が消し飛んだり、普段の生活ができなったりする不安がありました。
そこで今一度バックアップの必要性やどのように行うべきかを考え、「Btrfs のスナップショット取得と tar でのバックアップ」をするという結論になったため、その時の思考とやったことのログを残すために書きます。
この時の記録は Scrapbox にもあります。
懸念事項
バックアップを取っていない場合の心配事として主に以下の二つがありました。
- システムやカーネルのアップデートに万が一不具合があって壊れる (または
rm -rf /*
による事故)
- 間違えて rm コマンドなどでファイルを削除してしまう
前者はシステムバックアップ、後者はデータバックアップを行うことで対処できます。
システムが壊れるタイミングはパッケージマネージャのアップデート (paru -Syu
) 後で、PC が長い間使えないのは困るのでトラブル時は早急に復活させたいと思いました。
そのため、フルバックアップを毎回行い、バックアップのタイミングは週 1 回程度の paru -Syu
直前かつ、保管場所は同じ PC のストレージ以外が良いです。
またデータは刻々と移り変わっていくため、できれば毎日データバックアップがあると安心です。
Ext4 から Btrfs への移行
バックアップをするために、その前にスナップショットを取りたいと思いましたが、その方法は主に二つありました。
- LVM で論理ボリュームを確保してそこにスナップショットを格納する
- Btrfs の機能でスナップショットを取る
この時のファイルシステムは Ext4 でしたが、 Btrfs のスナップショットは CoW を用いた機能のため高速かつ効率的だと思い、 Ext4 から Btrfs に移行することにしました。
その時の手順は Scrapbox に書いてあります。
- 予め dd コマンドなどでバックアップを取っておく
- Live USB から Linux を起動
# cryptsetup open --type luks /dev/nvme0n1p2 vg0
でパスワードを入力し、暗号化されている移行元のパーティションをマウントできるようにする
# btrfs-convert /dev/mapper/vg0-root
でファイルシステムを変換
/etc/fstab
を編集 (UUID の変更、ファイルシステム名を btrfs
に変更、最後のフィールドを 0 に変更)
# <file system> <dir> <type> <options> <dump> <pass>
# /dev/mapper/vg0-root
UUID=a0bb3c42-0485-4367-90dd-5be4956344d3 / btrfs rw,relatime 0 0
# arch-chroot /dev/mapper/vg0-root
# mkinitcpio -p linux
# btrfs subvolume delete /ext2_saved
# btrfs balance start /
(これがなぜかエラーで失敗する)
# btrfs filesystem defragment -r -v -czstd /
で透過的自動圧縮を適用 (zstd
にした)
Btrfs でのサブボリューム設計
(追記:2023/05/21)
Btrfs でのサブボリューム設計を見直して /
と /home
を分けてスナップショットが取られるようになりました。
詳しいことは Scrapbox に書きました。
サブボリューム |
マウントポイント |
/ (id=5) |
/ |
@home |
/home |
@snapshots |
/snapshots |
この設計に則ってサブボリュームを生成する手順は以下です。
# btrfs subvolume create /@home
# rsync -av --links /home /@home
# mount /dev/mapper/vg0-root -o subvol=/@home /home
/etc/fstab
に UUID=6e62ce5d-407e-4265-abba-c4bf30ee8d06 /home btrfs rw,relatime,ssd,space_cache,subvolid=380,subvol=/@home,compress=zstd 0 0
を追加、 UUID=
は /dev/mapper/vg0-root
のものにして subvolid=
は適切なものにする
# mount -a
や再起動で fstab の変更を適用する
@snapshots
も同様に生成してからマウントする
バックアップの方針
バックアップの方針を以下のようにしました。
- システムバックアップは週 1 回程度で
paru -Syu
の前に行う
/
のバックアップを tar で取りクラウドに保管する
/home
のバックアップは tar で取らず、数時間毎に Btrfs でのスナップショットを取るのみ
スナップショットを取る
以下のようなスクリプトを作成し、 fcron のジョブで 2 時間毎にスナップショットを取るようにしました。
とりあえずは過去 5 個分のスナップショットをローカルに持っておくようにしました。
#!/bin/bash
# take a snapshot
date=$(date "+%F_%H-%M-%S")
if [ $1 = '/' ]; then
snapshot_dir="/snapshots/root"
elif [ $1 = '/home' ]; then
snapshot_dir="/snapshots/home"
else
echo "invalid argument: first argument must be / or /home"
exit 1
fi
if [ 5 -le $(ls -1U ${snapshot_dir} | wc -l) ]; then
oldest_snapshot="$(ls -rt ${snapshot_dir} | tail -n1)"
btrfs subvolume delete ${snapshot_dir}/${oldest_snapshot}
fi
if [ -e ${snapshot_dir}/${date} ]; then
echo "snapshot is already exist"
exit 1
else
btrfs subvolume snapshot -r $1 ${snapshot_dir}/${date}
fi
tar でのバックアップ
以下のスクリプトを手動で実行して、アーカイブファイルを手動でクラウドに保存します。
本当は Dropbox などでローカルにあるファイルと同期させる方がスマートで良かったのですが、複数回分のバックアップをローカルに置いておくとディスクの容量を圧迫して嫌なのでクラウドのみに保存するようにしました。
#!/bin/bash
# system backup
echo "taking a snapshot"
snapshot $1
echo "creating a tar archive file"
if [ $1 = '/' ]; then
dir_name="root"
elif [ $1 = '/home' ]; then
dir_name="home"
else
echo "invalid argument: first argument must be / or /home"
exit 1
fi
backup_dir="/backup"
snapshot_dir="/snapshots/${dir_name}"
exclude_file="/backup/exclude.txt"
latest_snapshot="$(ls -rt ${snapshot_dir} | head -n1)"
nice tar cvpf ${backup_dir}/${dir_name}_${latest_snapshot}.tar.xz \
--sparse \
--use-compress-prog=pixz \
--xattrs \
--exclude-from=${exclude_file} \
-C ${snapshot_dir}/${latest_snapshot} \
. \
> ${backup_dir}/${dir_name}_${latest_snapshot}.log
まとめ
Btrfs のスナップショットを fcron で数時間毎に取り、パッケージアップデートの前に tar でフルシステムバックアップを取ることで、システムの破損とユーザデータの誤消去に対処できるようになったと思います。
dotfiles に加えて、これらのバックアップを取ることで安心して PC を使えるようになりました。
参考