Difference between revisions of "Btrfs - Tips and tricks"
m (→GRUB: Cosmetic changes to wiki templates) |
m (→Booting into snapshots: Cosmetic changes for enhancing readability) |
||
(2 intermediate revisions by the same user not shown) | |||
Line 12: | Line 12: | ||
The root filesystem must have been installed into its own dedicated btrfs subvolume and the btrfs-root where all subvolumes reside has to be accessible. | The root filesystem must have been installed into its own dedicated btrfs subvolume and the btrfs-root where all subvolumes reside has to be accessible. | ||
− | + | {{hc|/etc/fstab| | |
− | + | <nowiki># ... | |
− | # ... | ||
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / btrfs defaults,subvol=__current/ROOT 0 0 | UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / btrfs defaults,subvol=__current/ROOT 0 0 | ||
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /run/btrfs-root btrfs defaults,compress=lzo 0 0 | UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /run/btrfs-root btrfs defaults,compress=lzo 0 0 | ||
Line 23: | Line 22: | ||
UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /home btrfs defaults,subvol=__current/home 0 0 | UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /home btrfs defaults,subvol=__current/home 0 0 | ||
# ... | # ... | ||
− | </nowiki> | + | </nowiki>}} |
==== Snapshot script ==== | ==== Snapshot script ==== | ||
Line 131: | Line 130: | ||
</nowiki>}} | </nowiki>}} | ||
− | ==== | + | ====systemd unit file==== |
Following [[systemd]] unit file will run the script every time the system manages to successfully boot into ''multi-user.target'': | Following [[systemd]] unit file will run the script every time the system manages to successfully boot into ''multi-user.target'': | ||
Line 154: | Line 153: | ||
=== Booting into snapshots === | === Booting into snapshots === | ||
− | In order to boot into a subvolume the ''rootflags=subvol='' option has to be used on the kernel line. The ''subvol='' mount options in {{ic|/etc/ | + | In order to boot into a subvolume the ''rootflags=subvol='' option has to be used on the kernel line. The ''subvol='' mount options in {{ic|/etc/fstab}} of the snapshot to boot into also have to be specified correctly. |
+ | {{Note|If using the example [[Btrfs - Tips and tricks#Snapshot script|script above]], the {{ic|/etc/fstab}} of the snapshot of the root subvolume is set automatically.}} | ||
==== [[GRUB]] ==== | ==== [[GRUB]] ==== |
Revision as of 13:44, 14 August 2013
Go back to Btrfs.
Contents
Snapshots
Automatic snapshots on each boot
It is possible to automatically save the then current state of a btrfs subvolume during system boot. Two files are needed to accomplish this, a script which snapshots btrfs subvolumes and a systemd unit file to run the script during the boot process.
Requirements
The root filesystem must have been installed into its own dedicated btrfs subvolume and the btrfs-root where all subvolumes reside has to be accessible.
/etc/fstab
# ... UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX / btrfs defaults,subvol=__current/ROOT 0 0 UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /run/btrfs-root btrfs defaults,compress=lzo 0 0 # just for the below example: UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /var btrfs defaults,subvol=__current/var 0 0 UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /opt btrfs defaults,subvol=__current/opt 0 0 UUID=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX /home btrfs defaults,subvol=__current/home 0 0 # ...
Snapshot script
An example script to snapshot the btrfs subvolumes mounted under / is listed further below. The script will automatically detect the names of all subvolumes mounted under / and create snapshots of the same names under a directory specified by the caller.
What the script does, is to delete all snapshots from the state the system was in at last boot, make new snapshots, and alter the /etc/fstab file of the snapshot of the root subvolume to allow it to be booted without manual configuration.
When called like this ...
# bash /usr/local/bin/snapshot_current_system_state.sh '/run/btrfs-root' '__current/ROOT' '__snapshot/__state_at_last_successful_boot'
the following structure will result:
$ btrfs subvolume list '/'
ID 257 gen 1134 top level 5 path __current/ROOT ID 258 gen 1137 top level 5 path __current/var ID 259 gen 1129 top level 5 path __current/opt ID 260 gen 1137 top level 5 path __current/home ID 277 gen 1128 top level 5 path __snapshot/__state_at_last_successful_boot/__current/ROOT ID 278 gen 1128 top level 5 path __snapshot/__state_at_last_successful_boot/__current/var ID 279 gen 1129 top level 5 path __snapshot/__state_at_last_successful_boot/__current/opt ID 280 gen 1130 top level 5 path __snapshot/__state_at_last_successful_boot/__current/home
Note that var, opt and home are subvolumes created by the caller in this example and mounted under '/'. The script detected and snapshotted them automatically. The resulting directory structure is:
/run/btrfs-root/__current/ROOT /run/btrfs-root/__current/var /run/btrfs-root/__current/opt /run/btrfs-root/__current/home /run/btrfs-root/__current/net /run/btrfs-root/__current/bak /run/btrfs-root/__snapshot/__state_at_last_successful_boot/__current/ROOT /run/btrfs-root/__snapshot/__state_at_last_successful_boot/__current/var /run/btrfs-root/__snapshot/__state_at_last_successful_boot/__current/opt /run/btrfs-root/__snapshot/__state_at_last_successful_boot/__current/home
The script below takes 3 parameters:
- The path of the btrfs filesystem root. E. g.
/run/btrfs-root
, - The name of the btrfs root subvolume as specified in /etc/fstab. E. g.
__current/ROOT
, - The path where the newly created snapshots will reside without its 1st parameter portion. E. g.
__snapshot/__state_at_last_successful_boot
(if the actual path is /run/btrfs-root/__snapshot/__state_at_last_successful_boot)
/usr/local/bin/snapshot_current_system_state.sh
#!/bin/sh # example call: # bash /usr/local/bin/snapshot_current_system_state.sh '/run/btrfs-root' '__current/ROOT' '__snapshot/__state_at_last_successful_boot' if [ $# -ne 3 ] then /usr/bin/echo -e "This script requires three parameters:\n1st parameter: The path of the btrfs filesystem root. e. g. /run/btrfs-root\n2nd parameter: The name of the btrfs root volume as specified in /etc/fstab. E. g. __current/ROOT\n3rd parameter: The path where the newly created snapshots will reside without its 1st parameter portion. E. g. __snapshot/__state_at_last_successful_boot\nCAUTION: This script will delete all snapshots of the same name as the regular volume names in the path parameter 3 is pointing to." exit 0 fi btrfs_root="${1}" # example: '/run/btrfs-root' path_to_root_volume="${2}" # example: '__current/ROOT' path_to_snapshots="${3}" # example: '__snapshot/__state_at_last_successful_boot' # take no snapshots when booted into a snapshot if [ -e '/SNAPSHOT-TIMESTAMP' ] then exit 0 fi # anti recursive snapshots for subvolume in $(/usr/bin/btrfs subvolume list '/' | /usr/bin/awk '{print $NF}') # scan do path_to_snapshot="${btrfs_root}/${path_to_snapshots}/${subvolume}" if [ -d "${path_to_snapshot}" ] then /usr/bin/btrfs subvolume delete "${path_to_snapshot}" fi done subvolumes="$(/usr/bin/btrfs subvolume list '/' | /usr/bin/awk '{print $NF}')" # rescan for subvolume in $subvolumes do snapshot_directory="${btrfs_root}/${path_to_snapshots}/$(/usr/bin/dirname ${subvolume})" if [ ! -d "${snapshot_directory}" ] then /usr/bin/mkdir -p "${snapshot_directory}" fi /usr/bin/btrfs subvolume snapshot "${btrfs_root}/${subvolume}" "${btrfs_root}/${path_to_snapshots}/${subvolume}" if [ "${subvolume}" = "${path_to_root_volume}" ] then timestamp="$(/usr/bin/date +%d.%m.%Y-%H:%M:%S)" /usr/bin/echo -e "Arch Linux --- state at last successful boot (nonpersistent) [${timestamp}]\n" > "${btrfs_root}/${path_to_snapshots}/${path_to_root_volume}/etc/issue" /usr/bin/echo "${timestamp}" > "${btrfs_root}/${path_to_snapshots}/${path_to_root_volume}/SNAPSHOT-TIMESTAMP" sed_path_to_snapshots="$(/usr/bin/echo ${path_to_snapshots} | /usr/bin/sed --posix --regexp-extended 's/\//\\\//g')" for subvolumeX in $(echo $subvolumes | /usr/bin/sed --posix --regexp-extended 's/\//\\\//g') do /usr/bin/sed --posix --regexp-extended "s/subvol=${subvolumeX}/subvol=${sed_path_to_snapshots}\/${subvolumeX}/g" --in-place "${btrfs_root}/${path_to_snapshots}/${path_to_root_volume}/etc/fstab" done fi done /usr/bin/sync
systemd unit file
Following systemd unit file will run the script every time the system manages to successfully boot into multi-user.target:
- Example unit file
/etc/systemd/system/snapshot_current_system_state_upon_boot.service
:
[Unit] Description=Takes a snapshot of each btrfs subvolume mounted under / after multi-user.target has been reached. After=multi-user.target [Service] Type=oneshot ExecStart=/bin/sh /usr/local/bin/snapshot_current_system_state.sh '/run/btrfs-root' '__current/ROOT' '__snapshot/__state_at_last_successful_boot' [Install] WantedBy=multi-user.target
The unit file has to be symlinked by systemd:
# systemctl enable snapshot_current_system_state_upon_boot.service
Booting into snapshots
In order to boot into a subvolume the rootflags=subvol= option has to be used on the kernel line. The subvol= mount options in /etc/fstab
of the snapshot to boot into also have to be specified correctly.
/etc/fstab
of the snapshot of the root subvolume is set automatically.GRUB
- Example menue entry
/etc/grub.d/40_custom
:
# .... menuentry "Arch Linux --- state at last successfull boot (nonpersistent)" { linux /vmlinuz-linux root=/dev/disk/by-uuid/<UUID of btrfs-root> rootflags=subvol=__snapshot/__state_at_last_successful_boot/__current/ROOT init=/usr/lib/systemd/systemd ro quiet initrd /initramfs-linux.img } # ...
/etc/grub.d/40_custom
has to be executable:
# chmod 700 /etc/grub.d/40_custom
/boot/grub/grub.cfg
has to be recreated:
# grub-mkconfig -o /boot/grub/grub.cfg