mirror of
https://github.com/Antynea/grub-btrfs.git
synced 2026-03-05 05:35:01 +08:00
Compare commits
151 Commits
v4.7.2
...
fix-bashis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2886ad7b3c | ||
|
|
72a3dc092b | ||
|
|
6cb200a50b | ||
|
|
346a9868b8 | ||
|
|
b8465d14db | ||
|
|
0bc09317d8 | ||
|
|
94d742d1d4 | ||
|
|
363d7da3a7 | ||
|
|
585268dad7 | ||
|
|
34b54de71c | ||
|
|
a8713bbd0b | ||
|
|
ac45f09af3 | ||
|
|
d41991979e | ||
|
|
99fc835e9c | ||
|
|
5e608f8d96 | ||
|
|
465b56107f | ||
|
|
7aa227b378 | ||
|
|
4ff82352bb | ||
|
|
98a5bbe8c5 | ||
|
|
abd2889464 | ||
|
|
25a9876ad4 | ||
|
|
d82ee289c3 | ||
|
|
ef150c17bb | ||
|
|
490720a13c | ||
|
|
ade5a91d55 | ||
|
|
9a8a1b7d50 | ||
|
|
d51c96433c | ||
|
|
f461ea9cf1 | ||
|
|
85571aab62 | ||
|
|
2bbfddc46a | ||
|
|
3ce858f18d | ||
|
|
dd96f22888 | ||
|
|
35429e02a4 | ||
|
|
04958d6e0b | ||
|
|
c6550d0d96 | ||
|
|
c7d4bbbe45 | ||
|
|
09a2a55ee4 | ||
|
|
8105a2edf7 | ||
|
|
879bec3697 | ||
|
|
e2937f6bff | ||
|
|
ec5ff8b4bc | ||
|
|
1556c345da | ||
|
|
8028a4376a | ||
|
|
0745117a76 | ||
|
|
2032502e09 | ||
|
|
1d53472569 | ||
|
|
8ea8046887 | ||
|
|
7586639f48 | ||
|
|
5ce2dfa640 | ||
|
|
44c9cd16d0 | ||
|
|
934a4a38e6 | ||
|
|
87f030f6e8 | ||
|
|
1d33404c78 | ||
|
|
89ef805e81 | ||
|
|
e03e87dd64 | ||
|
|
f131c38300 | ||
|
|
934ab213b0 | ||
|
|
f0ed56d242 | ||
|
|
29ec43e9a6 | ||
|
|
6980771cd2 | ||
|
|
bc167ffe00 | ||
|
|
b661e4e03f | ||
|
|
f594a56232 | ||
|
|
fe48642596 | ||
|
|
bfad9dcc1d | ||
|
|
e3d0792a74 | ||
|
|
efc4657aab | ||
|
|
9e34f53ef8 | ||
|
|
6f154329c7 | ||
|
|
4942989d7f | ||
|
|
91c4aac82c | ||
|
|
1d760ad730 | ||
|
|
02c3fbb23a | ||
|
|
13b6df8e9a | ||
|
|
2186d831cd | ||
|
|
c9620d5d18 | ||
|
|
33810a9274 | ||
|
|
1969132073 | ||
|
|
ead3849613 | ||
|
|
75f7d85261 | ||
|
|
d406ce795c | ||
|
|
b2b5307fe4 | ||
|
|
57687ac0ab | ||
|
|
a6e9caf6f4 | ||
|
|
36cee77bd8 | ||
|
|
de68795d70 | ||
|
|
4c63b65e9e | ||
|
|
bc09bbda65 | ||
|
|
19f62ee6e6 | ||
|
|
4580c0fa2c | ||
|
|
44573e5282 | ||
|
|
5805029c79 | ||
|
|
9064d61145 | ||
|
|
8c8ee200fd | ||
|
|
961675ca31 | ||
|
|
14c42b82eb | ||
|
|
6280f95139 | ||
|
|
d54f3d7366 | ||
|
|
c78bd25784 | ||
|
|
0182e11951 | ||
|
|
3dc1d89965 | ||
|
|
fc4a5a8e56 | ||
|
|
a146cd5c9d | ||
|
|
8dbe80c0bd | ||
|
|
79ae25ea5d | ||
|
|
ee3c366fa4 | ||
|
|
4f1aa38604 | ||
|
|
1accd5e272 | ||
|
|
2500ce8d30 | ||
|
|
d9f54afcb7 | ||
|
|
33ad3273d3 | ||
|
|
3b0d0c4ff7 | ||
|
|
66a218356a | ||
|
|
7dc240faa7 | ||
|
|
75e6408510 | ||
|
|
fbc33391cb | ||
|
|
63c3493504 | ||
|
|
02b925e4b5 | ||
|
|
9d436adf95 | ||
|
|
301752f300 | ||
|
|
3b857348cb | ||
|
|
f3d8e99cb8 | ||
|
|
af80fe7993 | ||
|
|
c7f403d2a2 | ||
|
|
e6898c0de8 | ||
|
|
a790ff054e | ||
|
|
df643361cc | ||
|
|
b0408225c1 | ||
|
|
8142691be1 | ||
|
|
bab78d4ed8 | ||
|
|
544d2e84ac | ||
|
|
b346727219 | ||
|
|
f1ca0db36d | ||
|
|
c4d0df3a97 | ||
|
|
c1cadccd1f | ||
|
|
8cc214fd0e | ||
|
|
81bde02b03 | ||
|
|
14bf041ba6 | ||
|
|
863107588c | ||
|
|
2851ecd72b | ||
|
|
679d000446 | ||
|
|
981777d745 | ||
|
|
3433754c69 | ||
|
|
db753a9ac8 | ||
|
|
83bf1da01e | ||
|
|
2f22fd8630 | ||
|
|
88a0320d62 | ||
|
|
87b816345b | ||
|
|
d68fdf5fff | ||
|
|
87168d2d50 | ||
|
|
a437b80a35 |
6
.codespellrc
Normal file
6
.codespellrc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[codespell]
|
||||||
|
skip = .git,*.pdf,*.svg,go.sum,.codespellrc
|
||||||
|
check-hidden = true
|
||||||
|
# ignore-regex =
|
||||||
|
# ist -- unfortunate variable
|
||||||
|
ignore-words-list = ist
|
||||||
22
.github/workflows/codespell.yml
vendored
Normal file
22
.github/workflows/codespell.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Codespell
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
name: Check for spelling errors
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Codespell
|
||||||
|
uses: codespell-project/actions-codespell@v2
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#! /usr/bin/env bash
|
#! /usr/bin/env sh
|
||||||
#
|
|
||||||
#
|
#
|
||||||
# Written by: Antynea
|
# Written by: Antynea
|
||||||
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
|
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
|
||||||
@@ -7,32 +6,30 @@
|
|||||||
#
|
#
|
||||||
# Purpose:
|
# Purpose:
|
||||||
# Improves Grub by adding "btrfs snapshots" to the Grub menu.
|
# Improves Grub by adding "btrfs snapshots" to the Grub menu.
|
||||||
# You can start your system on a "snapshot" from the Grub menu.
|
# You can boot your system on a "snapshot" from the Grub menu.
|
||||||
# Supports manual snapshots, snapper ...
|
# Supports manual snapshots, snapper, timeshift ...
|
||||||
# Warning : booting on read-only snapshots can be tricky
|
# Warning : booting on read-only snapshots can be tricky.
|
||||||
# (Read about it, https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
|
# (Read about it, https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
|
||||||
#
|
#
|
||||||
# What this script does:
|
# What this script does:
|
||||||
# - Automatically List snapshots existing on root partition (btrfs).
|
# - Automatically List snapshots existing on root partition (btrfs).
|
||||||
# - Automatically Detect if "/boot" is in separate partition.
|
# - Automatically Detect if "/boot" is in separate partition.
|
||||||
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots.
|
# - Automatically Detect kernel, initramfs and intel/amd microcode in "/boot" directory on snapshots.
|
||||||
# - Automatically Create corresponding "menuentry" in grub.cfg
|
# - Automatically Create corresponding "menuentry" in grub.cfg.
|
||||||
# - Automatically detect snapper and use snapper's snapshot description if available.
|
# - Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
|
||||||
# - Automatically generate grub.cfg if you use the provided systemd service.
|
# - Automatically generate grub.cfg if you use the provided systemd service.
|
||||||
#
|
#
|
||||||
# Installation:
|
# Installation:
|
||||||
# - Run `make install` or look into Makefile for instructions on where to put each file.
|
# - Refer to https://github.com/Antynea/grub-btrfs#%EF%B8%8F-installation
|
||||||
#
|
#
|
||||||
# Customization:
|
# Customization:
|
||||||
# Refer to config for the list of available options and their default values.
|
# You have the possibility to modify many parameters in /etc/default/grub-btrfs/config.
|
||||||
# Place your configurations to /etc/default/grub-btrfs/config.
|
# Read more here https://github.com/Antynea/grub-btrfs#installation- an in the manpage
|
||||||
|
# 'man grub-btrfs'
|
||||||
#
|
#
|
||||||
# Automatically update Grub
|
# Automatically update Grub
|
||||||
# If you would like Grub to automatically update when a snapshots is made or deleted:
|
# If you would like grub-btrfs menu to automatically update when a snapshot is created or deleted:
|
||||||
# - Use systemctl start/enable grub-btrfs.path
|
# - Refer to https://github.com/Antynea/grub-btrfs#-automatically-update-grub-upon-snapshot.
|
||||||
# - grub-btrfs.path automatically (re)generates grub.cfg when a modification appears in /.snapshots folder (by default).
|
|
||||||
# - If your snapshots aren't mounted in /.snapshots, you must modify the watch folder using systemctl edit grub-btrfs.path
|
|
||||||
# - See https://github.com/Antynea/grub-btrfs#automatically-update-grub
|
|
||||||
#
|
#
|
||||||
# Special thanks for assistance and contributions:
|
# Special thanks for assistance and contributions:
|
||||||
# - My friends
|
# - My friends
|
||||||
@@ -41,73 +38,117 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
prefix="/usr"
|
|
||||||
exec_prefix="/usr"
|
|
||||||
datarootdir="/usr/share"
|
|
||||||
sysconfdir="/etc"
|
sysconfdir="/etc"
|
||||||
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
|
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
|
||||||
|
|
||||||
[[ -f "$grub_btrfs_config" ]] && . "$grub_btrfs_config"
|
# shellcheck disable=SC1090
|
||||||
. "$datarootdir/grub/grub-mkconfig_lib"
|
[ -f "$grub_btrfs_config" ] && . "$grub_btrfs_config"
|
||||||
. "${sysconfdir}/default/grub"
|
# shellcheck disable=SC1091
|
||||||
|
[ -f "${sysconfdir}/default/grub" ] && . "${sysconfdir}/default/grub"
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
print_error()
|
||||||
|
{
|
||||||
|
err_msg="$*"
|
||||||
|
bug_report="If you think an error has occurred, please file a bug report at \"https://github.com/Antynea/grub-btrfs\""
|
||||||
|
printf "%s\n" "${err_msg}" "${bug_report}" >&2 ;
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# parse arguments
|
||||||
|
while getopts :V-: opt; do
|
||||||
|
case "$opt" in
|
||||||
|
-)
|
||||||
|
case "${OPTARG}" in
|
||||||
|
version)
|
||||||
|
printf "Version %s\n" "${GRUB_BTRFS_VERSION}" >&2 ;
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac;;
|
||||||
|
V)
|
||||||
|
printf "Version %s\n" "${GRUB_BTRFS_VERSION}" >&2 ;
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf "Unknown flag, exiting...\n"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
## Exit the script, if:
|
||||||
|
[ "$(echo "$GRUB_BTRFS_DISABLE" | tr '[:upper:]' '[:lower:]')" = 'true' ] && print_error "GRUB_BTRFS_DISABLE is set to true (default=false)"
|
||||||
|
if ! type btrfs >/dev/null 2>&1; then print_error "btrfs-progs isn't installed"; fi
|
||||||
|
# shellcheck disable=SC1090,SC2015
|
||||||
|
[ -f "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" ] && . "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" || print_error "grub-mkconfig_lib couldn't be found"
|
||||||
|
# shellcheck disable=SC2005
|
||||||
|
if echo "$(btrfs filesystem df / 2>&1)" | grep "not a btrfs filesystem" >/dev/null 2>&1; then print_error "Root filesystem isn't btrfs"; fi
|
||||||
|
|
||||||
|
printf "Detecting snapshots ...\n" >&2 ;
|
||||||
|
|
||||||
### Variables in /etc/default/grub-btrfs/config
|
|
||||||
## Disable Grub-btrfs (default=active)
|
|
||||||
[[ "${GRUB_BTRFS_DISABLE:-"false"}" == "true" ]] && exit 0
|
|
||||||
## Submenu name
|
## Submenu name
|
||||||
distro=$(awk -F "=" '/^NAME=/ {gsub(/"/, "", $2); print $2}' /etc/os-release)
|
distro=$(awk -F "=" '/^NAME=/ {gsub(/"/, "", $2); print $2}' /etc/os-release) # escape '
|
||||||
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"}
|
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"}
|
||||||
## Prefix entry
|
## Limit snapshots to show in the Grub menu (default=50)
|
||||||
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"}
|
|
||||||
## Limit snapshots to show in the Grub menu
|
|
||||||
limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
|
limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
|
||||||
## How to sort snapshots list
|
## How to sort snapshots list
|
||||||
btrfssubvolsort=(--sort="${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}")
|
btrfs_subvolume_sort="--sort=${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}"
|
||||||
## Snapper's config name
|
|
||||||
snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
|
|
||||||
## Customize GRUB directory, where "grub.cfg" file is saved
|
## Customize GRUB directory, where "grub.cfg" file is saved
|
||||||
grub_directory=${GRUB_BTRFS_GRUB_DIRNAME:-"/boot/grub"}
|
grub_directory=${GRUB_BTRFS_GRUB_DIRNAME:-"/boot/grub"}
|
||||||
## Customize BOOT directory, where kernels/initrams/microcode is saved.
|
## Customize BOOT directory, where kernels/initrams/microcode is saved.
|
||||||
boot_directory=${GRUB_BTRFS_BOOT_DIRNAME:-"/boot"}
|
boot_directory=${GRUB_BTRFS_BOOT_DIRNAME:-"/boot"}
|
||||||
|
## Customize GRUB-BTRFS.cfg directory, where "grub-btrfs.cfg" file is saved
|
||||||
|
grub_btrfs_directory=${GRUB_BTRFS_GBTRFS_DIRNAME:-${grub_directory}}
|
||||||
|
## Customize directory where "grub-btrfs.cfg" file is searched for by grub
|
||||||
|
grub_btrfs_search_directory=${GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME:-"\${prefix}"}
|
||||||
## Password protection management for submenu
|
## Password protection management for submenu
|
||||||
# Protection support for submenu (--unrestricted)
|
# Protection support for submenu (--unrestricted)
|
||||||
case "${GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU:-"false"}" in
|
case "$(echo "$GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU" | tr '[:upper:]' '[:lower:]')" in
|
||||||
true) unrestricted_access_submenu="--unrestricted ";;
|
true) unrestricted_access_submenu="--unrestricted ";;
|
||||||
*) unrestricted_access_submenu=""
|
*) unrestricted_access_submenu=""
|
||||||
esac
|
esac
|
||||||
# Authorized users (--users foo,bar)
|
# Authorized users (--users foo,bar)
|
||||||
if [ ! -z "${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS}" ] ; then
|
if [ -n "${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS}" ] ; then
|
||||||
protection_authorized_users="--users ${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS} "
|
protection_authorized_users="--users ${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS} "
|
||||||
fi
|
fi
|
||||||
|
|
||||||
### variables script
|
## Probe information of Root and Boot devices
|
||||||
## Probe info "Boot partition"
|
# Probe info "Root partition"
|
||||||
# Boot device
|
# shellcheck disable=SC2154 # grub_probe is provided by grub environment
|
||||||
boot_device=$(${grub_probe} --target=device ${boot_directory})
|
root_device=$(${grub_probe} --target=device /) # Root device
|
||||||
# hints string
|
# shellcheck disable=SC2086 # we actually need word splitting here if we have several root devices (e.g. RAID)
|
||||||
boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null)
|
root_uuid=$(${grub_probe} --device ${root_device} --target="fs_uuid" 2>/dev/null) # UUID of the root device
|
||||||
# UUID of the boot partition
|
root_uuid_subvolume=$(btrfs subvolume show / 2>/dev/null) || print_error "UUID of the root subvolume is not available"; # If UUID of root subvolume is not available, then exit
|
||||||
boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null)
|
root_uuid_subvolume=$(awk -F":" 'match($1, /(^[ \t]+UUID)/) {sub(/^[ \t]+/, "", $2); print $2}' <<EOF
|
||||||
# Type filesystem of boot partition
|
"$root_uuid_subvolume"
|
||||||
boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null)
|
EOF
|
||||||
## Probe info "Root partition"
|
) # UUID of the root subvolume '
|
||||||
# Type filesystem of root partition
|
# Probe info "Boot partition"
|
||||||
root_fs=$(${grub_probe} --target="fs" / 2>/dev/null)
|
# shellcheck disable=SC2086 # we actually need word splitting here if we have several devices
|
||||||
# Root device
|
boot_device=$(${grub_probe} --target=device ${boot_directory}) # Boot device
|
||||||
root_device=$(${grub_probe} --target=device /)
|
# shellcheck disable=SC2086 # we actually need word splitting here if we have several devices
|
||||||
# UUID of the root partition
|
boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null) # UUID of the boot device
|
||||||
root_uuid=$(${grub_probe} --device ${root_device} --target="fs_uuid" 2>/dev/null)
|
boot_uuid_subvolume=$(btrfs subvolume show "$boot_directory" 2>/dev/null) || boot_uuid_subvolume=" UUID: $root_uuid_subvolume"; # If boot folder isn't a subvolume, then UUID=root_uuid_subvolume
|
||||||
|
boot_uuid_subvolume=$(awk -F":" 'match($1, /(^[ \t]+UUID)/) {sub(/^[ \t]+/, "", $2); print $2}' <<EOF
|
||||||
|
"$boot_uuid_subvolume"
|
||||||
|
EOF
|
||||||
|
) # UUID of the boot subvolume '
|
||||||
|
# shellcheck disable=SC2086 # we actually need word splitting here if we have several devices
|
||||||
|
boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null) # hints string
|
||||||
|
# shellcheck disable=SC2086 # we actually need word splitting here if we have several devices
|
||||||
|
boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null) # Type filesystem of boot device
|
||||||
|
|
||||||
## Parameters passed to the kernel
|
## Parameters passed to the kernel
|
||||||
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
|
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT $GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS"
|
||||||
## Mount point location
|
## Mount point location
|
||||||
gbgmp=$(mktemp -d)
|
grub_btrfs_mount_point=$(mktemp -dt grub-btrfs.XXXXXXXXXX)
|
||||||
## Class for theme
|
## Class for theme
|
||||||
CLASS="--class snapshots --class gnu-linux --class gnu --class os"
|
CLASS="--class snapshots --class gnu-linux --class gnu --class os"
|
||||||
## save IFS
|
## save IFS
|
||||||
oldIFS=$IFS
|
oldIFS=$IFS
|
||||||
## Detect uuid requirement (lvm,btrfs...)
|
## Detect uuid requirement (lvm,btrfs...)
|
||||||
check_uuid_required() {
|
check_uuid_required() {
|
||||||
if [ "x${root_uuid}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
|
if [ "${root_uuid}" = "" ] || [ "${GRUB_DISABLE_LINUX_UUID}" = "true" ] \
|
||||||
|| ! test -e "/dev/disk/by-uuid/${root_uuid}" \
|
|| ! test -e "/dev/disk/by-uuid/${root_uuid}" \
|
||||||
|| ( test -e "${root_device}" && uses_abstraction "${root_device}" lvm ); then
|
|| ( test -e "${root_device}" && uses_abstraction "${root_device}" lvm ); then
|
||||||
LINUX_ROOT_DEVICE=${root_device}
|
LINUX_ROOT_DEVICE=${root_device}
|
||||||
@@ -115,62 +156,82 @@ else
|
|||||||
LINUX_ROOT_DEVICE=UUID=${root_uuid}
|
LINUX_ROOT_DEVICE=UUID=${root_uuid}
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
## Detect rootflags
|
||||||
### Error Handling
|
detect_rootflags()
|
||||||
print_error()
|
|
||||||
{
|
{
|
||||||
local arg="$@"
|
fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${grub_btrfs_mount_point}/${snap_dir_name_trim}/etc/fstab" \
|
||||||
local nothing_to_do="If you think an error has occurred , please file a bug report at \" https://github.com/Antynea/grub-btrfs \"\nNothing to do. Abort.\n"
|
| sed -E 's/^.*[[:space:]]([[:graph:]]+)$/\1/;s/,?subvol(id)?=[^,$]+//g;s/^,//')
|
||||||
printf "${arg}\n${nothing_to_do}" >&2 ;
|
rootflags="rootflags=${fstabflags:+$fstabflags,}${GRUB_BTRFS_ROOTFLAGS:+$GRUB_BTRFS_ROOTFLAGS,}"
|
||||||
exit 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test_btrfs()
|
unmount_grub_btrfs_mount_point()
|
||||||
{
|
{
|
||||||
[[ "$root_fs" != "btrfs" ]] && print_error "Root partition isn't a btrfs filesystem.\nThis script only supports snapshots of the btrfs filesystem."
|
if [ -d "$grub_btrfs_mount_point" ]; then
|
||||||
set +e
|
wait=true
|
||||||
type btrfs >/dev/null 2>&1
|
wait_max=0
|
||||||
if [[ $? -ne 0 ]]; then
|
printf "Unmount %s .." "$grub_btrfs_mount_point" >&2;
|
||||||
print_error "Unable to retrieve info from btrfs filesystem, make sure you have btrfs-progs on your system."
|
while $wait; do
|
||||||
|
if grep -qs "$grub_btrfs_mount_point" /proc/mounts; then
|
||||||
|
wait_max=$((1+wait_max))
|
||||||
|
if umount "$grub_btrfs_mount_point" >/dev/null 2>&1; then
|
||||||
|
wait=false # umount successful
|
||||||
|
printf " Success\n" >&2;
|
||||||
|
elif [ $wait_max -eq 10 ]; then
|
||||||
|
printf "\nWarning: Unable to unmount %s in %s\n" "$root_device" "$grub_btrfs_mount_point" >&2;
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
printf "." >&2 ; # output to show that the script is alive
|
||||||
|
sleep 2 # wait 2 seconds before retry
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
wait=false # not mounted
|
||||||
|
printf " Success\n" >&2;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$wait" != true ]; then
|
||||||
|
if ! rm -d "$grub_btrfs_mount_point" >/dev/null 2>&1; then
|
||||||
|
printf "Unable to delete %s: Device or resource is busy\n" "$grub_btrfs_mount_point" >&2;
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
set -e
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
### Script
|
|
||||||
## Create entry
|
## Create entry
|
||||||
entry()
|
entry()
|
||||||
{
|
{
|
||||||
echo "$@" >> "$grub_directory/grub-btrfs.cfg"
|
echo "$@" >> "$grub_btrfs_directory/grub-btrfs.new"
|
||||||
}
|
}
|
||||||
|
|
||||||
## menu entries
|
## menu entries
|
||||||
make_menu_entries()
|
make_menu_entries()
|
||||||
{
|
{
|
||||||
## \" required for snap,kernels,init,microcode with space in their name
|
## \" required for snap,kernels,init,microcode with space in their name
|
||||||
entry "submenu '$title_menu' {
|
entry "submenu '${title_menu}' {
|
||||||
submenu '---> $title_menu <---' { echo }"
|
submenu '${title_submenu}' { echo }"
|
||||||
for k in "${name_kernel[@]}"; do
|
for k in "${name_kernel[@]}"; do
|
||||||
[[ ! -f "${boot_dir}"/"${k}" ]] && continue;
|
[ ! -f "${boot_dir}"/"${k}" ] && continue;
|
||||||
kversion=${k#*"-"}
|
kversion=${k#*"-"}
|
||||||
for i in "${name_initramfs[@]}"; do
|
for i in "${name_initramfs[@]}"; do
|
||||||
prefix_i=${i%%"-"*}
|
if [ "${name_initramfs}" != "x" ] ; then
|
||||||
suffix_i=${i#*"-"}
|
# prefix_i=${i%%"-"*}
|
||||||
alt_suffix_i=${i##*"-"}
|
suffix_i=${i#*"-"}
|
||||||
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
|
# alt_suffix_i=${i##*"-"}
|
||||||
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
|
# shellcheck disable=SC2269 # this is a way to exit the if..elif..
|
||||||
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
|
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
|
||||||
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
|
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
|
||||||
else continue ;
|
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
|
||||||
fi
|
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
|
||||||
for u in "${name_microcode[@]}"; do
|
else continue;
|
||||||
if [[ "${name_microcode}" != "x" ]] ; then
|
|
||||||
entry "
|
|
||||||
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
|
||||||
else
|
|
||||||
entry "
|
|
||||||
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
|
||||||
fi
|
fi
|
||||||
entry "\
|
for u in "${name_microcode[@]}"; do
|
||||||
|
if [ "${name_microcode}" != "x" ] ; then
|
||||||
|
entry "
|
||||||
|
menuentry ' "${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
||||||
|
else
|
||||||
|
entry "
|
||||||
|
menuentry ' "${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
||||||
|
fi
|
||||||
|
entry "\
|
||||||
if [ x\$feature_all_video_module = xy ]; then
|
if [ x\$feature_all_video_module = xy ]; then
|
||||||
insmod all_video
|
insmod all_video
|
||||||
fi
|
fi
|
||||||
@@ -181,21 +242,53 @@ make_menu_entries()
|
|||||||
else
|
else
|
||||||
search --no-floppy --fs-uuid --set=root ${boot_uuid}
|
search --no-floppy --fs-uuid --set=root ${boot_uuid}
|
||||||
fi
|
fi
|
||||||
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
|
echo 'Loading Snapshot: "${snap_date_trim}" "${snap_dir_name_trim}"'
|
||||||
echo 'Loading Kernel: "${k}" ...'
|
echo 'Loading Kernel: "${k}" ...'
|
||||||
linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" rw ${kernel_parameters} rootflags=subvol=\""${snap_dir_name}"\""
|
linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name_trim}"\""
|
||||||
if [[ "${name_microcode}" != "x" ]] ; then
|
if [ "${name_microcode}" != "x" ] ; then
|
||||||
entry "\
|
entry "\
|
||||||
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
|
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
|
||||||
initrd \"${boot_dir_root_grub}/"${u}"\" \"${boot_dir_root_grub}/"${i}"\""
|
initrd \"${boot_dir_root_grub}/"${u}"\" \"${boot_dir_root_grub}/"${i}"\""
|
||||||
else
|
else
|
||||||
entry "\
|
entry "\
|
||||||
echo 'Loading Initramfs: "${i}" ...'
|
echo 'Loading Initramfs: "${i}" ...'
|
||||||
initrd \"${boot_dir_root_grub}/"${i}"\""
|
initrd \"${boot_dir_root_grub}/"${i}"\""
|
||||||
fi
|
fi
|
||||||
entry " }"
|
entry " }"
|
||||||
count_warning_menuentries=$((1+$count_warning_menuentries))
|
count_warning_menuentries=$((1+count_warning_menuentries))
|
||||||
done
|
done
|
||||||
|
else
|
||||||
|
for u in "${name_microcode[@]}"; do
|
||||||
|
if [ "${name_microcode}" != "x" ] ; then
|
||||||
|
entry "
|
||||||
|
menuentry ' "${k}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
||||||
|
else
|
||||||
|
entry "
|
||||||
|
menuentry ' "${k}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
|
||||||
|
fi
|
||||||
|
entry "\
|
||||||
|
if [ x\$feature_all_video_module = xy ]; then
|
||||||
|
insmod all_video
|
||||||
|
fi
|
||||||
|
set gfxpayload=keep
|
||||||
|
insmod ${boot_fs}
|
||||||
|
if [ x\$feature_platform_search_hint = xy ]; then
|
||||||
|
search --no-floppy --fs-uuid --set=root ${boot_hs} ${boot_uuid}
|
||||||
|
else
|
||||||
|
search --no-floppy --fs-uuid --set=root ${boot_uuid}
|
||||||
|
fi
|
||||||
|
echo 'Loading Snapshot: "${snap_date_trim}" "${snap_dir_name_trim}"'
|
||||||
|
echo 'Loading Kernel: "${k}" ...'
|
||||||
|
linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name_trim}"\""
|
||||||
|
if [ "${name_microcode}" != "x" ] ; then
|
||||||
|
entry "\
|
||||||
|
echo 'Loading Microcode: "${u}" ...'
|
||||||
|
initrd \"${boot_dir_root_grub}/"${u}"\""
|
||||||
|
fi
|
||||||
|
entry " }"
|
||||||
|
count_warning_menuentries=$((1+count_warning_menuentries))
|
||||||
|
done
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
entry "}"
|
entry "}"
|
||||||
@@ -203,151 +296,179 @@ make_menu_entries()
|
|||||||
|
|
||||||
## Trim a string from leading and trailing whitespaces
|
## Trim a string from leading and trailing whitespaces
|
||||||
trim() {
|
trim() {
|
||||||
local var="$*"
|
var="$*"
|
||||||
var="${var#"${var%%[![:space:]]*}"}"
|
var="${var#"${var%%[![:space:]]*}"}"
|
||||||
var="${var%"${var##*[![:space:]]}"}"
|
var="${var%"${var##*[![:space:]]}"}"
|
||||||
echo -n "$var"
|
printf '%s' "$var"
|
||||||
}
|
}
|
||||||
|
|
||||||
## List of snapshots on filesystem
|
## List of snapshots on filesystem
|
||||||
snapshot_list()
|
snapshot_list()
|
||||||
{
|
{
|
||||||
# Query info from snapper if it is installed
|
snapper_info="info.xml"
|
||||||
type snapper >/dev/null 2>&1
|
timeshift_info="info.json"
|
||||||
if [ $? -eq 0 ]; then
|
date_snapshots=()
|
||||||
if [ -s "/etc/snapper/configs/$snapper_config" ]; then
|
path_snapshots=()
|
||||||
printf "Info: snapper detected, using config '$snapper_config'\n" >&2
|
type_snapshots=()
|
||||||
local snapper_ids=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 1))
|
description_snapshots=()
|
||||||
local snapper_types=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 2))
|
|
||||||
|
|
||||||
IFS=$'\n'
|
|
||||||
local snapper_descriptions=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | rev | cut -d'|' -f 2 | rev))
|
|
||||||
else
|
|
||||||
printf "Warning: snapper detected but config '$snapper_config' does not exist\n" >&2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
|
for snap in $(btrfs subvolume list -sa "${btrfs_subvolume_sort}" /); do # Parse btrfs snapshots
|
||||||
# Parse btrfs snapshots
|
|
||||||
local entries=()
|
|
||||||
local ids=()
|
|
||||||
local max_entry_length=0
|
|
||||||
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
|
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
snap=($snap)
|
snap=(${snap})
|
||||||
local snap_path_name=${snap[@]:13:${#snap[@]}}
|
local path_snapshot=${snap[@]:13:${#snap[@]}}
|
||||||
|
if [ "$path_snapshot" = "DELETED" ]; then continue; fi # Discard deleted snapshots
|
||||||
# Discard deleted snapshots
|
[[ ${path_snapshot%%"/"*} == "<FS_TREE>" ]] && path_snapshot=${path_snapshot#*"/"} # Remove the "<FS_TREE>" string at the beginning of the path
|
||||||
if [ "$snap_path_name" = "DELETED" ]; then continue; fi
|
|
||||||
[[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"}
|
|
||||||
|
|
||||||
# ignore specific path during run "grub-mkconfig"
|
# ignore specific path during run "grub-mkconfig"
|
||||||
if [ ! -z "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH}" ] ; then
|
if [ -n "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH}" ] ; then
|
||||||
for isp in ${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]} ; do
|
for isp in "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]}" ; do
|
||||||
[[ "${snap_path_name}" == "${isp}" ]] && continue 2;
|
[ "${path_snapshot}" = "${isp}" ] && continue 2;
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [ ! -z "${GRUB_BTRFS_IGNORE_PREFIX_PATH}" ] ; then
|
if [ -n "${GRUB_BTRFS_IGNORE_PREFIX_PATH}" ] ; then
|
||||||
for isp in ${GRUB_BTRFS_IGNORE_PREFIX_PATH[@]} ; do
|
for isp in "${GRUB_BTRFS_IGNORE_PREFIX_PATH[@]}" ; do
|
||||||
[[ "${snap_path_name}" == "${isp}"/* ]] && continue 2;
|
[[ "${path_snapshot}" == "${isp}"/* ]] && continue 2;
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
[ ! -d "$grub_btrfs_mount_point/$path_snapshot/boot" ] && continue; # Discard snapshots without /boot folder
|
||||||
|
|
||||||
|
# Parse Snapper & timeshift & yabsnap information
|
||||||
|
local type_snapshot="N/A"
|
||||||
|
local description_snapshot="N/A"
|
||||||
|
|
||||||
|
# path to yabsnap snapshot meta data
|
||||||
|
local yabsnap_info
|
||||||
|
yabsnap_info="$grub_btrfs_mount_point/${path_snapshot%"/"*}/$(echo "${snap[13]}" | awk -F'/' '{print $3 "-meta.json"}')"
|
||||||
|
|
||||||
|
if [[ -s "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info" ]] ; then
|
||||||
|
type_snapshot=$(awk -F"<|>" 'match($2, /^type/) {print $3}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info") # search matching string beginning "type"
|
||||||
|
description_snapshot=$(awk -F"<|>" 'match($2, /^description/) {print $3}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info") # search matching string beginning "description"
|
||||||
|
elif [[ -s "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info" ]] ; then
|
||||||
|
type_snapshot=$(awk -F" : " 'match($1, /^[ \t]+"tags"/) {gsub(/"|,/,"");print $2}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info") # search matching string beginning "tags"
|
||||||
|
description_snapshot=$(awk -F" : " 'match($1, /^[ \t]+"comments"/) {gsub(/"|,/,"");print $2}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info") # search matching string beginning "comments" fix '
|
||||||
|
elif [[ -s $yabsnap_info ]] ; then
|
||||||
|
type_snapshot=$(grep -P '^\s*"trigger"' $yabsnap_info | awk -F'"' '{print $4}') # search matching string beginning "trigger"
|
||||||
|
description_snapshot=$(grep -P '^\s*"comment"' $yabsnap_info | awk -F'"' '{print $4}') # search matching string beginning "comment"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z "$type_snapshot" ] && type_snapshot=("N/A")
|
||||||
|
[ -z "$description_snapshot" ] && description_snapshot=("N/A")
|
||||||
|
|
||||||
|
# ignore specific {type,tag,description} of snapshot during run "grub-mkconfig"
|
||||||
|
if [ -n "${GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE}" ] ; then
|
||||||
|
for ist in "${GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE[@]}" ; do
|
||||||
|
[ "${type_snapshot}" = "${ist}" ] && continue 2;
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [ -n "${GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION}" ] ; then
|
||||||
|
for isd in "${GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION[@]}" ; do
|
||||||
|
[ "${description_snapshot}" = "${isd}" ] && continue 2;
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# detect if /boot directory exists
|
local date_snapshot="${snap[@]:10:2}"
|
||||||
[[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue;
|
date_snapshots+=("$date_snapshot")
|
||||||
|
path_snapshots+=("$path_snapshot")
|
||||||
|
type_snapshots+=("$type_snapshot")
|
||||||
|
description_snapshots+=("$description_snapshot")
|
||||||
|
done
|
||||||
|
|
||||||
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
|
# Find max length of a snapshot date, needed for pretty formatting
|
||||||
ids+=("$id")
|
local max_date_length=0
|
||||||
|
for i in "${date_snapshots[@]}"; do
|
||||||
|
local length="${#i}"
|
||||||
|
[ "$length" -gt "$max_date_length" ] && max_date_length=$length
|
||||||
|
done
|
||||||
|
|
||||||
local entry="${snap[@]:10:2} | ${snap_path_name}"
|
# Find max length of a snapshot name, needed for pretty formatting
|
||||||
entries+=("$entry")
|
local max_path_length=0
|
||||||
|
for i in "${path_snapshots[@]}"; do
|
||||||
# Find max length of a snapshot entry, needed for pretty formatting
|
local length="${#i}"
|
||||||
local length="${#entry}"
|
[ "$length" -gt "$max_path_length" ] && max_path_length=$length
|
||||||
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Find max length of a snapshot type, needed for pretty formatting
|
# Find max length of a snapshot type, needed for pretty formatting
|
||||||
local max_type_length=0
|
local max_type_length=0
|
||||||
for id in "${ids[@]}"; do
|
for i in "${type_snapshots[@]}"; do
|
||||||
for j in "${!snapper_ids[@]}"; do
|
local length="${#i}"
|
||||||
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
|
[ "$length" -gt "$max_type_length" ] && max_type_length=$length
|
||||||
if [[ "$snapper_id" == "$id" ]]; then
|
|
||||||
local snapper_type=$(trim "${snapper_types[$j]}")
|
|
||||||
local length="${#snapper_type}"
|
|
||||||
[[ "$length" -gt "$max_type_length" ]] && max_type_length=$length
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
done
|
done
|
||||||
|
|
||||||
for i in "${!entries[@]}"; do
|
# Find max length of a snapshot description, needed for pretty formatting
|
||||||
local id="${ids[$i]}"
|
local max_description_length=0
|
||||||
local entry="${entries[$i]}"
|
for i in "${description_snapshots[@]}"; do
|
||||||
for j in "${!snapper_ids[@]}"; do
|
local length="${#i}"
|
||||||
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
|
[[ "$length" -gt "$max_description_length" ]] && max_description_length=$length
|
||||||
# remove other non numeric characters
|
done
|
||||||
snapper_id="${snapper_id//\*/}"
|
|
||||||
snapper_id="${snapper_id//\+/}"
|
for i in "${!path_snapshots[@]}"; do
|
||||||
snapper_id="${snapper_id//-/}"
|
printf -v entry "%-${max_date_length}s | %-${max_path_length}s | %-${max_type_length}s | %-${max_description_length}s |" "${date_snapshots[$i]}" "${path_snapshots[$i]}" "${type_snapshots[$i]}" "${description_snapshots[$i]}"
|
||||||
if [[ "$snapper_id" == "$id" ]]; then
|
|
||||||
local snapper_type=$(trim "${snapper_types[$j]}")
|
|
||||||
local snapper_description=$(trim "${snapper_descriptions[$j]}")
|
|
||||||
printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "$entry"
|
echo "$entry"
|
||||||
done
|
done
|
||||||
|
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
## Detect kernels in "/boot"
|
## Parse snapshots in snapshot_list
|
||||||
|
parse_snapshot_list()
|
||||||
|
{
|
||||||
|
snap_date=" $(echo "$item" | cut -d'|' -f1)" # column_1, first space is necessary for pretty formatting
|
||||||
|
snap_date_trim="$(trim "$snap_date")"
|
||||||
|
|
||||||
|
snap_dir_name="$(echo "$item" | cut -d'|' -f2)" # column_2
|
||||||
|
snap_dir_name_trim="$(trim "$snap_dir_name")"
|
||||||
|
# shellcheck disable=SC2034 # Used by "title_format" function
|
||||||
|
snap_snapshot="$snap_dir_name"
|
||||||
|
# shellcheck disable=SC2034 # Used by "title_format" function
|
||||||
|
snap_type="$(echo "$item" | cut -d'|' -f3)" # column_3
|
||||||
|
# shellcheck disable=SC2034 # Used by "title_format" function
|
||||||
|
snap_description="$(echo "$item" | cut -d'|' -f4)" # column_4
|
||||||
|
}
|
||||||
|
|
||||||
|
## Detect kernels in "boot_directory"
|
||||||
detect_kernel()
|
detect_kernel()
|
||||||
{
|
{
|
||||||
list_kernel=()
|
list_kernel=""
|
||||||
# Original kernel (auto-detect)
|
# Original kernel (auto-detect)
|
||||||
for okernel in "${boot_dir}"/vmlinuz-* \
|
for okernel in "${boot_dir}"/vmlinuz-* \
|
||||||
"${boot_dir}"/vmlinux-* \
|
"${boot_dir}"/vmlinux-* \
|
||||||
"${boot_dir}"/kernel-* ; do
|
"${boot_dir}"/kernel-* ; do
|
||||||
[[ ! -f "${okernel}" ]] && continue;
|
[ ! -f "${okernel}" ] && continue;
|
||||||
list_kernel+=("$okernel")
|
list_kernel="${list_kernel} $okernel"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Custom name kernel in GRUB_BTRFS_NKERNEL
|
# Custom name kernel in "GRUB_BTRFS_NKERNEL"
|
||||||
if [ ! -z "${GRUB_BTRFS_NKERNEL}" ] ; then
|
if [ -n "${GRUB_BTRFS_NKERNEL}" ] ; then
|
||||||
for ckernel in "${boot_dir}/${GRUB_BTRFS_NKERNEL[@]}" ; do
|
for ckernel in "${boot_dir}"/${GRUB_BTRFS_NKERNEL} ; do
|
||||||
[[ ! -f "${ckernel}" ]] && continue;
|
[ ! -f "${ckernel}" ] && continue;
|
||||||
list_kernel+=("$ckernel")
|
list_kernel="${list_kernel} $okernel"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## Detect initramfs in "/boot"
|
## Detect initramfs in "boot_directory"
|
||||||
detect_initramfs()
|
detect_initramfs()
|
||||||
{
|
{
|
||||||
list_initramfs=()
|
list_initramfs=()
|
||||||
# Original initramfs (auto-detect)
|
# Original initramfs (auto-detect)
|
||||||
for oinitramfs in "${boot_dir}"/initrd.img-* \
|
for oinitramfs in "${boot_dir}"/initrd.img-* \
|
||||||
"${boot_dir}"/initrd-*.img \
|
"${boot_dir}"/initramfs-* \
|
||||||
"${boot_dir}"/initrd-*.gz \
|
"${boot_dir}"/initrd-* ; do
|
||||||
"${boot_dir}"/initramfs-*.img \
|
[ ! -f "${oinitramfs}" ] && continue;
|
||||||
"${boot_dir}"/initramfs-*.gz ; do
|
|
||||||
[[ ! -f "${oinitramfs}" ]] && continue;
|
|
||||||
list_initramfs+=("$oinitramfs")
|
list_initramfs+=("$oinitramfs")
|
||||||
done
|
done
|
||||||
|
|
||||||
# Custom name initramfs in GRUB_BTRFS_NINIT
|
# Custom name initramfs in "GRUB_BTRFS_NINIT"
|
||||||
if [ ! -z "${GRUB_BTRFS_NINIT}" ] ; then
|
if [ -n "${GRUB_BTRFS_NINIT}" ] ; then
|
||||||
for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
|
for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
|
||||||
[[ ! -f "${cinitramfs}" ]] && continue;
|
[ ! -f "${cinitramfs}" ] && continue;
|
||||||
list_initramfs+=("$cinitramfs")
|
list_initramfs+=("$cinitramfs")
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
if [ -z "${list_initramfs}" ]; then list_initramfs=(x); fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## Detect microcode in "/boot"
|
## Detect microcode in "boot_directory"
|
||||||
detect_microcode()
|
detect_microcode()
|
||||||
{
|
{
|
||||||
list_ucode=()
|
list_ucode=()
|
||||||
@@ -359,43 +480,54 @@ detect_microcode()
|
|||||||
"${boot_dir}"/amd-ucode.img \
|
"${boot_dir}"/amd-ucode.img \
|
||||||
"${boot_dir}"/early_ucode.cpio \
|
"${boot_dir}"/early_ucode.cpio \
|
||||||
"${boot_dir}"/microcode.cpio; do
|
"${boot_dir}"/microcode.cpio; do
|
||||||
[[ ! -f "${oiucode}" ]] && continue;
|
[ ! -f "${oiucode}" ] && continue;
|
||||||
list_ucode+=("$oiucode")
|
list_ucode+=("$oiucode")
|
||||||
done
|
done
|
||||||
|
|
||||||
# Custom name microcode in GRUB_BTRFS_CUSTOM_MICROCODE
|
# Custom name microcode in "GRUB_BTRFS_CUSTOM_MICROCODE"
|
||||||
if [ ! -z "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
|
if [ -n "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
|
||||||
for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
|
for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
|
||||||
[[ ! -f "${cucode}" ]] && continue
|
[ ! -f "${cucode}" ] && continue
|
||||||
list_ucode+=("$cucode")
|
list_ucode+=("$cucode")
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
|
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
|
||||||
}
|
}
|
||||||
|
|
||||||
## Show full path snapshot or only name
|
## Title format in Grub-menu
|
||||||
path_snapshot()
|
declare -A title_column=( [date]=Date [snapshot]=Snapshot [type]=Type [description]=Description ) # Column title that appears in the header
|
||||||
{
|
|
||||||
case "${GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:-"true"}" in
|
|
||||||
true) name_snapshot=("${snap_full_name}");;
|
|
||||||
*) name_snapshot=("${snap_full_name#*"/"}")
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
## Title format in grub-menu
|
|
||||||
title_format()
|
title_format()
|
||||||
{
|
{
|
||||||
case "${GRUB_BTRFS_TITLE_FORMAT:-"p/d/n"}" in
|
title_menu="|" # "|" is for visuals only
|
||||||
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
|
title_submenu="|" # "|" is for visuals only
|
||||||
p/d) title_menu="${prefixentry} ${snap_date_time}";;
|
[ -z "${GRUB_BTRFS_TITLE_FORMAT}" ] && GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description"); # Default parameters
|
||||||
p/n) title_menu="${prefixentry} ${name_snapshot}";;
|
for key in "${!GRUB_BTRFS_TITLE_FORMAT[@]}"; do
|
||||||
d/n) title_menu="${snap_date_time} ${name_snapshot}";;
|
[[ ${GRUB_BTRFS_TITLE_FORMAT[$key],,} != "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key]}],,}" ]] && continue; # User used wrong parameter
|
||||||
n/d) title_menu="${name_snapshot} ${snap_date_time}";;
|
declare -n var="snap_${GRUB_BTRFS_TITLE_FORMAT[$key],,}" # $var is a indirect variable
|
||||||
p) title_menu="${prefixentry}";;
|
if [[ "${#var}" -lt "${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}" ]]; then # Add extra spaces if length of $var is smaller than the length of column, needed for pretty formatting
|
||||||
d) title_menu="${snap_date_time}";;
|
printf -v var "%-$(((${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}-${#var})+${#var}))s" "${var}";
|
||||||
n) title_menu="${name_snapshot}";;
|
fi
|
||||||
*) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}"
|
var="$(sed "s/'//g" <(echo "${var}"))"
|
||||||
esac
|
title_menu+="${var}|"
|
||||||
|
title_submenu+=" $(trim "${var}") |"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
# Adds a header to the grub-btrfs.cfg file
|
||||||
|
header_menu()
|
||||||
|
{
|
||||||
|
header_entry=""
|
||||||
|
[ -z "${GRUB_BTRFS_TITLE_FORMAT}" ] && GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description"); # Default parameters
|
||||||
|
for key in "${!GRUB_BTRFS_TITLE_FORMAT[@]}"; do
|
||||||
|
[[ ${GRUB_BTRFS_TITLE_FORMAT[$key],,} != "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key]}],,}" ]] && continue; # User used wrong parameter
|
||||||
|
declare -n var="snap_${GRUB_BTRFS_TITLE_FORMAT[$key],,}" # $var is a indirect variable
|
||||||
|
# Center alignment, needed for pretty formatting
|
||||||
|
local lenght_title_column_left=$((${#var}-${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}))
|
||||||
|
((lenght_title_column_left%2)) && lenght_title_column_left=$((lenght_title_column_left+1)); # If the difference is an odd number, add an extra space
|
||||||
|
lenght_title_column_left=$(((lenght_title_column_left/2)+${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}));
|
||||||
|
local lenght_title_column_right=$(((${#var}-lenght_title_column_left)+1)) #+1 is necessary for extra "|" character
|
||||||
|
header_entry+=$(printf "%${lenght_title_column_left}s%${lenght_title_column_right}s" "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}" "|") # Final "|" is for visuals only
|
||||||
|
done
|
||||||
|
sed -i "1imenuentry '|${header_entry}' { echo }" "$grub_btrfs_directory/grub-btrfs.new" # First "|" is for visuals only
|
||||||
}
|
}
|
||||||
|
|
||||||
## List of kernels, initramfs and microcode in snapshots
|
## List of kernels, initramfs and microcode in snapshots
|
||||||
@@ -404,139 +536,115 @@ boot_bounded()
|
|||||||
# Initialize menu entries
|
# Initialize menu entries
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
for item in $(snapshot_list); do
|
for item in $(snapshot_list); do
|
||||||
[[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
|
[ "${limit_snap_show}" -le 0 ] && break; # fix: limit_snap_show=0
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
|
parse_snapshot_list
|
||||||
snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
|
boot_dir="$grub_btrfs_mount_point/$snap_dir_name_trim$boot_directory"
|
||||||
snap_dir_name="$(trim "$snap_dir_name")"
|
|
||||||
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
|
|
||||||
snap_date_time="$(trim "$snap_date_time")"
|
|
||||||
|
|
||||||
boot_dir="$gbgmp/$snap_dir_name$boot_directory"
|
|
||||||
# Kernel (Original + custom kernel)
|
|
||||||
detect_kernel
|
detect_kernel
|
||||||
if [ -z "${list_kernel}" ]; then continue; fi
|
if [ -z "${list_kernel}" ]; then continue; fi
|
||||||
|
# TODO
|
||||||
name_kernel=("${list_kernel[@]##*"/"}")
|
name_kernel=("${list_kernel[@]##*"/"}")
|
||||||
# Initramfs (Original + custom initramfs)
|
|
||||||
detect_initramfs
|
detect_initramfs
|
||||||
if [ -z "${list_initramfs}" ]; then continue; fi
|
|
||||||
name_initramfs=("${list_initramfs[@]##*"/"}")
|
name_initramfs=("${list_initramfs[@]##*"/"}")
|
||||||
# microcode (auto-detect + custom microcode)
|
|
||||||
detect_microcode
|
detect_microcode
|
||||||
name_microcode=("${list_ucode[@]##*"/"}")
|
name_microcode=("${list_ucode[@]##*"/"}")
|
||||||
|
detect_rootflags
|
||||||
|
title_format
|
||||||
|
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" # convert "boot_directory" to root of GRUB (e.g /boot become /)
|
||||||
|
make_menu_entries
|
||||||
# show snapshot found during run "grub-mkconfig"
|
# show snapshot found during run "grub-mkconfig"
|
||||||
if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
|
if [ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]; then
|
||||||
printf "Found snapshot: %s\n" "$item" >&2 ;
|
printf "Found snapshot: %s\n" "$item" >&2 ;
|
||||||
fi
|
fi
|
||||||
# Show full path snapshot or only name
|
# Limit snapshots found during run "grub-mkconfig"
|
||||||
path_snapshot
|
count_limit_snap=$((1+count_limit_snap))
|
||||||
# Title format in grub-menu
|
[ "$count_limit_snap" -ge "$limit_snap_show" ] && break;
|
||||||
title_format
|
|
||||||
# convert /boot directory to root of GRUB (e.g /boot become /)
|
|
||||||
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
|
|
||||||
# Make menuentries
|
|
||||||
make_menu_entries
|
|
||||||
### Limit snapshots found during run "grub-mkconfig"
|
|
||||||
count_limit_snap=$((1+$count_limit_snap))
|
|
||||||
[[ $count_limit_snap -ge $limit_snap_show ]] && break;
|
|
||||||
# Limit generation of menuentries if exceeds 250
|
|
||||||
# [[ $count_warning_menuentries -ge 250 ]] && break;
|
|
||||||
done
|
done
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_separate()
|
boot_separate()
|
||||||
{
|
{
|
||||||
boot_dir="${boot_directory}"
|
boot_dir="${boot_directory}"
|
||||||
# convert /boot directory to root of GRUB (e.g /boot become /)
|
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" # convert "boot_directory" to root of GRUB (e.g /boot become /)
|
||||||
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
|
|
||||||
|
|
||||||
# Kernel (Original + custom kernel)
|
|
||||||
detect_kernel
|
detect_kernel
|
||||||
if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
|
if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
|
||||||
name_kernel=("${list_kernel[@]##*"/"}")
|
name_kernel=("${list_kernel[@]##*"/"}")
|
||||||
# Initramfs (Original + custom initramfs)
|
|
||||||
detect_initramfs
|
detect_initramfs
|
||||||
if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi
|
|
||||||
name_initramfs=("${list_initramfs[@]##*"/"}")
|
name_initramfs=("${list_initramfs[@]##*"/"}")
|
||||||
# microcode (auto-detect + custom microcode)
|
|
||||||
detect_microcode
|
detect_microcode
|
||||||
name_microcode=("${list_ucode[@]##*"/"}")
|
name_microcode=("${list_ucode[@]##*"/"}")
|
||||||
|
|
||||||
# Initialize menu entries
|
# Initialize menu entries
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
for item in $(snapshot_list); do
|
for item in $(snapshot_list); do
|
||||||
[[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
|
[ "${limit_snap_show}" -le 0 ] && break; # fix: limit_snap_show=0
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
|
parse_snapshot_list
|
||||||
snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
|
detect_rootflags
|
||||||
snap_dir_name="$(trim "$snap_dir_name")"
|
title_format
|
||||||
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
|
make_menu_entries
|
||||||
snap_date_time="$(trim "$snap_date_time")"
|
|
||||||
# show snapshot found during run "grub-mkconfig"
|
# show snapshot found during run "grub-mkconfig"
|
||||||
if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
|
if [ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]; then
|
||||||
printf "Found snapshot: %s\n" "$item" >&2 ;
|
printf "Found snapshot: %s\n" "$item" >&2 ;
|
||||||
fi
|
fi
|
||||||
# Show full path snapshot or only name
|
|
||||||
path_snapshot
|
|
||||||
# Title format in grub-menu
|
|
||||||
title_format
|
|
||||||
# Make menuentries
|
|
||||||
make_menu_entries
|
|
||||||
# Limit snapshots found during run "grub-mkconfig"
|
# Limit snapshots found during run "grub-mkconfig"
|
||||||
count_limit_snap=$((1+$count_limit_snap))
|
count_limit_snap=$((1+count_limit_snap))
|
||||||
[[ $count_limit_snap -ge $limit_snap_show ]] && break;
|
[ "$count_limit_snap" -ge "$limit_snap_show" ] && break;
|
||||||
# Limit generation of menuentries if exceeds 250
|
|
||||||
# [[ $count_warning_menuentries -ge 250 ]] && break;
|
|
||||||
done
|
done
|
||||||
IFS=$oldIFS
|
IFS=$oldIFS
|
||||||
}
|
}
|
||||||
|
|
||||||
### Start
|
rm -f "$grub_btrfs_directory/grub-btrfs.new"
|
||||||
printf "Detecting snapshots ...\n" >&2 ;
|
true > "$grub_btrfs_directory/grub-btrfs.new" # Create a "grub-btrfs.new" file in "grub_btrfs_directory"
|
||||||
# Only support btrfs snapshots
|
# Create a backup of the "$grub_btrfs_directory/grub-btrfs.cfg" file if exist
|
||||||
test_btrfs
|
if [ -e "$grub_btrfs_directory/grub-btrfs.cfg" ]; then
|
||||||
# Delete existing config
|
mv -f "$grub_btrfs_directory/grub-btrfs.cfg" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
|
||||||
#rm -f --preserve-root "$grub_directory/grub-btrfs.cfg"
|
fi
|
||||||
> "$grub_directory/grub-btrfs.cfg"
|
|
||||||
# Create mount point then mounting
|
# Create mount point then mounting
|
||||||
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp
|
[ ! -d "$grub_btrfs_mount_point" ] && mkdir -p "$grub_btrfs_mount_point"
|
||||||
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
|
mount -o ro,subvolid=5 /dev/disk/by-uuid/"$root_uuid" "$grub_btrfs_mount_point/" > /dev/null
|
||||||
# Count menuentries
|
trap "unmount_grub_btrfs_mount_point" EXIT # unmounting mount point on EXIT signal
|
||||||
count_warning_menuentries=0
|
count_warning_menuentries=0 # Count menuentries
|
||||||
# Count snapshots
|
count_limit_snap=0 # Count snapshots
|
||||||
count_limit_snap=0
|
|
||||||
# detect uuid requirement
|
|
||||||
check_uuid_required
|
check_uuid_required
|
||||||
# Detects if /boot is a separate partition
|
# Detects if /boot is a separate partition
|
||||||
if [[ "${GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION:-"false"}" == "true" ]]; then
|
[ "$(echo "$GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION}" | tr '[:upper:]' '[:lower:]')" = "true" ] && printf "Override boot partition detection : enable \n" >&2 && boot_separate;
|
||||||
printf "Info: Override boot partition detection : enable \n" >&2 ;
|
if [ "$root_uuid" != "$boot_uuid" ] || [ "$root_uuid_subvolume" != "$boot_uuid_subvolume" ]; then boot_separate ; else boot_bounded ; fi
|
||||||
boot_separate
|
|
||||||
else
|
|
||||||
if [[ "$root_uuid" != "$boot_uuid" ]]; then
|
|
||||||
printf "Info: Separate boot partition detected \n" >&2 ;
|
|
||||||
boot_separate
|
|
||||||
else
|
|
||||||
printf "Info: Separate boot partition not detected \n" >&2 ;
|
|
||||||
boot_bounded
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# unmounting mount point
|
|
||||||
umount $gbgmp
|
|
||||||
# Show warn, menuentries exceeds 250 entries
|
|
||||||
[[ $count_warning_menuentries -ge 250 ]] && printf "Generated ${count_warning_menuentries} total GRUB entries. You might experience issues loading snapshots menu in GRUB.\n" >&2 ;
|
|
||||||
# printf "menuentries = $count_warning_menuentries \n" >&2 ;
|
|
||||||
# Show total found snapshots
|
|
||||||
if [[ "${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}" = "true" && ! -z "${count_limit_snap}" && "${count_limit_snap}" != "0" ]]; then
|
|
||||||
printf "Found ${count_limit_snap} snapshot(s)\n" >&2 ;
|
|
||||||
fi
|
|
||||||
# if no snapshot found, exit
|
|
||||||
if [[ "${count_limit_snap}" = "0" || -z "${count_limit_snap}" ]]; then
|
|
||||||
print_error "No snapshots found."
|
|
||||||
fi
|
|
||||||
# Make a submenu in GRUB (grub.cfg)
|
# Make a submenu in GRUB (grub.cfg)
|
||||||
cat << EOF
|
cat << EOF
|
||||||
|
if [ ! -e "${grub_btrfs_search_directory}/grub-btrfs.cfg" ]; then
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
submenu '${submenuname}' ${protection_authorized_users}${unrestricted_access_submenu}{
|
submenu '${submenuname}' ${protection_authorized_users}${unrestricted_access_submenu}{
|
||||||
configfile "\${prefix}/grub-btrfs.cfg"
|
configfile "${grub_btrfs_search_directory}/grub-btrfs.cfg"
|
||||||
}
|
}
|
||||||
|
fi
|
||||||
EOF
|
EOF
|
||||||
### End
|
# Show warn, menuentries exceeds 250 entries
|
||||||
|
[ $count_warning_menuentries -ge 250 ] && printf "Generated %s total GRUB entries. You might experience issues loading snapshots menu in GRUB.\n" "${count_warning_menuentries}" >&2 ;
|
||||||
|
# Show total found snapshots
|
||||||
|
if [ "${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}" = "true" ] && [ -n "${count_limit_snap}" ] && [ "${count_limit_snap}" != "0" ]; then
|
||||||
|
printf "Found %s snapshot(s)\n" "${count_limit_snap}" >&2 ;
|
||||||
|
fi
|
||||||
|
# if no snapshot found, delete the "$grub_btrfs_directory/grub-btrfs.new" file and the "$grub_btrfs_directory/grub-btrfs.cfg.bkp" file and exit
|
||||||
|
if [ "${count_limit_snap}" = "0" ] || [ -z "${count_limit_snap}" ]; then
|
||||||
|
rm -f "$grub_btrfs_directory/grub-btrfs.new" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
|
||||||
|
print_error "No snapshots found."
|
||||||
|
fi
|
||||||
|
# Move "grub-btrfs.new" to "grub-btrfs.cfg"
|
||||||
|
header_menu
|
||||||
|
# shellcheck disable=SC2154 # bindir is provided by grub environment
|
||||||
|
if "${bindir}/${GRUB_BTRFS_SCRIPT_CHECK:-grub-script-check}" "$grub_btrfs_directory/grub-btrfs.new"; then
|
||||||
|
cat "$grub_btrfs_directory/grub-btrfs.new" > "$grub_btrfs_directory/grub-btrfs.cfg"
|
||||||
|
rm -f "$grub_btrfs_directory/grub-btrfs.new" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
|
||||||
|
else
|
||||||
|
if [ -e "$grub_btrfs_directory/grub-btrfs.cfg.bkp" ]; then
|
||||||
|
mv -f "$grub_btrfs_directory/grub-btrfs.cfg.bkp" "$grub_btrfs_directory/grub-btrfs.cfg"
|
||||||
|
fi
|
||||||
|
print_error "Syntax errors were detected in generated ${grub_btrfs_directory}/grub-btrfs.new file. The old grub-btrfs.cfg file (if present) have been restored."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# warn when this script is run but there is no entry in grub.cfg
|
||||||
|
grep "snapshots-btrfs" "${grub_directory}/grub.cfg" >/dev/null 2>&1 || printf "\nWARNING: '%s' needs to run at least once to generate the snapshots (sub)menu entry in grub the main menu. \
|
||||||
|
After that this script can run alone to generate the snapshot entries.\n\n" "${GRUB_BTRFS_MKCONFIG:-grub-mkconfig}" >&2 ;
|
||||||
|
|||||||
160
Makefile
160
Makefile
@@ -1,31 +1,153 @@
|
|||||||
PKGNAME ?= grub-btrfs
|
PKGNAME ?= grub-btrfs
|
||||||
PREFIX ?= /usr
|
PREFIX ?= /usr
|
||||||
|
|
||||||
|
INITCPIO ?= false
|
||||||
|
SYSTEMD ?= true
|
||||||
|
OPENRC ?= false
|
||||||
|
|
||||||
|
BOOT_DIR_DEBIAN ?= /boot/grub
|
||||||
|
BOOT_DIR_FEDORA ?= /boot/grub2
|
||||||
|
|
||||||
|
GRUB_UPDATE_EXCLUDE ?= false
|
||||||
|
INSTALL_DOCS ?= true
|
||||||
|
|
||||||
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
|
||||||
LIB_DIR = $(DESTDIR)$(PREFIX)/lib
|
LIB_DIR = $(DESTDIR)$(PREFIX)/lib
|
||||||
|
BIN_DIR = $(DESTDIR)$(PREFIX)/bin
|
||||||
|
MAN_DIR = $(SHARE_DIR)/man
|
||||||
|
|
||||||
.PHONY: install
|
TEMP_DIR = ./temp
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: install uninstall clean help
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
@if test "$(shell id -u)" != 0; then \
|
||||||
|
echo "You are not root, run this target as root please."; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo " Installing "
|
||||||
|
@echo
|
||||||
|
@echo " :::::::: ::::::::: ::: ::: ::::::::: ::::::::: ::::::::::: ::::::::: :::::::::: :::::::: "
|
||||||
|
@echo " :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: "
|
||||||
|
@echo " +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ "
|
||||||
|
@echo " :#: +#++:++#: +#+ +:+ +#++:++#+ +#++:++#++:++ +#++:++#+ +#+ +#++:++#: :#::+::# +#++:++#++ "
|
||||||
|
@echo " +#+ +#+# +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ "
|
||||||
|
@echo " #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# "
|
||||||
|
@echo " ######## ### ### ######## ######### ######### ### ### ### ### ######## "
|
||||||
|
@echo
|
||||||
|
@echo " For further information visit https://github.com/Antynea/grub-btrfs or read the man page: 'man grub-btrfs'"
|
||||||
|
@echo
|
||||||
|
@rm -rf "${TEMP_DIR}"
|
||||||
|
@mkdir "${TEMP_DIR}"
|
||||||
|
@chmod 777 ${TEMP_DIR}
|
||||||
|
@cp manpages/grub-btrfs.8.man ${TEMP_DIR}/grub-btrfs.8
|
||||||
|
@if test "$(INSTALL_DOCS)" = true; then \
|
||||||
|
echo "Installing manpages..."; \
|
||||||
|
install -Dm644 -t "${MAN_DIR}/man8" "${TEMP_DIR}/grub-btrfs.8"; \
|
||||||
|
fi
|
||||||
|
@cp manpages/grub-btrfsd.8.man ${TEMP_DIR}/grub-btrfsd.8
|
||||||
|
@if test "$(INSTALL_DOCS)" = true; then \
|
||||||
|
install -Dm644 -t "${MAN_DIR}/man8" "${TEMP_DIR}/grub-btrfsd.8"; \
|
||||||
|
fi
|
||||||
@install -Dm755 -t "$(DESTDIR)/etc/grub.d/" 41_snapshots-btrfs
|
@install -Dm755 -t "$(DESTDIR)/etc/grub.d/" 41_snapshots-btrfs
|
||||||
@install -Dm644 -t "$(DESTDIR)/etc/default/grub-btrfs/" config
|
@install -Dm644 -t "$(DESTDIR)/etc/default/grub-btrfs/" config
|
||||||
@install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.service
|
@install -Dm744 -t "$(BIN_DIR)/" grub-btrfsd;
|
||||||
@install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.path
|
@# Systemd init system
|
||||||
@install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE
|
@if test "$(SYSTEMD)" = true; then \
|
||||||
@install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-install" "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs" # Arch Linux only
|
echo "Installing systemd .service file"; \
|
||||||
@install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-hook" "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs" # Arch Linux only
|
install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfsd.service; \
|
||||||
@install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md
|
fi
|
||||||
@install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
|
@# OpenRC init system
|
||||||
|
@if test "$(OPENRC)" = true; then \
|
||||||
|
echo "Installing openRC init.d & conf.d file"; \
|
||||||
|
install -Dm744 grub-btrfsd.initd "$(DESTDIR)/etc/init.d/grub-btrfsd"; \
|
||||||
|
install -Dm644 grub-btrfsd.confd "$(DESTDIR)/etc/conf.d/grub-btrfsd"; \
|
||||||
|
fi
|
||||||
|
@# Arch Linux like distros only :
|
||||||
|
@if test "$(INITCPIO)" = true; then \
|
||||||
|
echo "Installing initcpio hook"; \
|
||||||
|
install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-install" "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"; \
|
||||||
|
install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-hook" "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"; \
|
||||||
|
fi
|
||||||
|
@if test "$(INSTALL_DOCS)" = true; then \
|
||||||
|
echo "Installing docs..."; \
|
||||||
|
install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE; \
|
||||||
|
install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md; \
|
||||||
|
install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"; \
|
||||||
|
fi
|
||||||
|
@if command -v grub-mkconfig > /dev/null && [ -e "$(BOOT_DIR_DEBIAN)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
|
||||||
|
echo "Updating the GRUB menu..."; \
|
||||||
|
grub-mkconfig -o "$(BOOT_DIR_DEBIAN)/grub.cfg"; \
|
||||||
|
fi
|
||||||
|
@if command -v grub2-mkconfig > /dev/null && [ -e "$(BOOT_DIR_FEDORA)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
|
||||||
|
echo "Updating the GRUB menu..."; \
|
||||||
|
grub2-mkconfig -o "$(BOOT_DIR_FEDORA)/grub.cfg"; \
|
||||||
|
fi
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f "$(DESTDIR)/etc/grub.d/41_snapshots-btrfs"
|
@echo "Uninstalling grub-btrfs"
|
||||||
rm -f "$(DESTDIR)/etc/default/grub-btrfs/config"
|
@if test "$(shell id -u)" != 0; then \
|
||||||
rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.service"
|
echo "You are not root, run this target as root please."; \
|
||||||
rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.path"
|
exit 1; \
|
||||||
rm -f "$(SHARE_DIR)/licenses/$(PKGNAME)/LICENSE"
|
fi
|
||||||
rm -f "$(DESTDIR)/boot/grub/grub-btrfs.cfg"
|
@grub_dirname="$$(grep -oP '^[[:space:]]*GRUB_BTRFS_GRUB_DIRNAME=\K.*' "$(DESTDIR)/etc/default/grub-btrfs/config" | sed "s|\s*#.*||;s|(\s*\(.\+\)\s*)|\1|;s|['\"]||g")"; \
|
||||||
rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs" # Arch Linux only
|
rm -f "$${grub_dirname:-/boot/grub}/grub-btrfs.cfg"
|
||||||
rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs" # Arch Linux only
|
@rm -f "$(DESTDIR)/etc/default/grub-btrfs/config"
|
||||||
rm -rf "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md
|
@rm -f "$(DESTDIR)/etc/grub.d/41_snapshots-btrfs"
|
||||||
rm -rf "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
|
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfsd.service"
|
||||||
rmdir --ignore-fail-on-non-empty "$(DESTDIR)/etc/default/grub-btrfs"
|
@rm -f "$(BIN_DIR)/grub-btrfsd;"
|
||||||
|
@rm -f "$(DESTDIR)/etc/init.d/grub-btrfsd;"
|
||||||
|
@rm -f "$(DESTDIR)/etc/conf.d/grub-btrfsd;"
|
||||||
|
@rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"
|
||||||
|
@rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"
|
||||||
|
@rm -f "$(MAN_DIR)/man8/grub-btrfs.8.bz2"
|
||||||
|
@rm -f "$(MAN_DIR)/man8/grub-btrfsd.8.bz2"
|
||||||
|
@# Arch Linux UNlike distros only :
|
||||||
|
@if test "$(INITCPIO)" != true && test -d "$(LIB_DIR)/initcpio"; then \
|
||||||
|
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio/install" || :; \
|
||||||
|
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio/hooks" || :; \
|
||||||
|
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio" || :; \
|
||||||
|
fi
|
||||||
|
@rm -f "$(SHARE_DIR)/doc/$(PKGNAME)/README.md"
|
||||||
|
@rm -f "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
|
||||||
|
@rm -f "$(SHARE_DIR)/licenses/$(PKGNAME)/LICENSE"
|
||||||
|
@rmdir --ignore-fail-on-non-empty "$(SHARE_DIR)/doc/$(PKGNAME)/" || :
|
||||||
|
@rmdir --ignore-fail-on-non-empty "$(SHARE_DIR)/licenses/$(PKGNAME)/" || :
|
||||||
|
@rmdir --ignore-fail-on-non-empty "$(DESTDIR)/etc/default/grub-btrfs" || :
|
||||||
|
@if command -v grub-mkconfig > /dev/null && [ -e "$(BOOT_DIR_DEBIAN)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
|
||||||
|
echo "Updating the GRUB menu..."; \
|
||||||
|
grub-mkconfig -o "$(BOOT_DIR_DEBIAN)/grub.cfg"; \
|
||||||
|
fi
|
||||||
|
@if command -v grub2-mkconfig > /dev/null && [ -e "$(BOOT_DIR_FEDORA)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
|
||||||
|
echo "Updating the GRUB menu..."; \
|
||||||
|
grub2-mkconfig -o "$(BOOT_DIR_FEDORA)/grub.cfg"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "Deleting ./temp"
|
||||||
|
@rm -rf "${TEMP_DIR}"
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo
|
||||||
|
@echo "Usage: $(MAKE) [ <parameter>=<value> ... ] [ <action> ]"
|
||||||
|
@echo "Example: $(MAKE) OPENRC=true SYSTEMD=false install"
|
||||||
|
@echo
|
||||||
|
@echo " actions: install"
|
||||||
|
@echo " uninstall"
|
||||||
|
@echo " help"
|
||||||
|
@echo
|
||||||
|
@echo " parameter | type | description | defaults"
|
||||||
|
@echo " --------------------+------+-------------------------------------------------------+----------------------------"
|
||||||
|
@echo " DESTDIR | path | install destination | <unset>"
|
||||||
|
@echo " PREFIX | path | system tree prefix | '/usr'"
|
||||||
|
@echo " BOOT_DIR_DEBIAN | path | boot data location (Debian, Ubuntu, Gentoo, Arch...) | '/boot/grub'"
|
||||||
|
@echo " BOOT_DIR_FEDORA | path | boot data location (Fedora, RHEL, CentOS, Rocky...) | '/boot/grub2'"
|
||||||
|
@echo " SHARE_DIR | path | shared data location | '\$$(DESTDIR)\$$(PREFIX)/share'"
|
||||||
|
@echo " LIB_DIR | path | system libraries location | '\$$(DESTDIR)\$$(PREFIX)/lib'"
|
||||||
|
@echo " PKGNAME | name | name of the distributed package | 'grub-btrfs'"
|
||||||
|
@echo " INITCPIO | bool | include mkinitcpio hook | false"
|
||||||
|
@echo " SYSTEMD | bool | include unit files | true"
|
||||||
|
@echo " OPENRC | bool | include OpenRc daemon | false"
|
||||||
|
@echo " GRUB_UPDATE_EXCLUDE | bool | Do not update grub after installation | false"
|
||||||
|
@echo
|
||||||
|
|||||||
348
README.md
348
README.md
@@ -1,75 +1,325 @@
|
|||||||
[](https://github.com/Antynea/grub-btrfs/releases)
|
[](https://github.com/Antynea/grub-btrfs/releases)
|
||||||

|

|
||||||
|
|
||||||
## grub-btrfs
|
## 💻 grub-btrfs
|
||||||
|
|
||||||
This is a version 4.xx of grub-btrfs
|
|
||||||
##### BTC donation address: `1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt`
|
##### BTC donation address: `1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt`
|
||||||
##
|
- - -
|
||||||
### Description
|
### 🔎 Description:
|
||||||
Improves Grub by adding "btrfs snapshots" to the Grub menu.
|
grub-btrfs improves the grub bootloader by adding a btrfs snapshots sub-menu, allowing the user to boot into snapshots.
|
||||||
|
|
||||||
You can start your system on a "snapshot" from the Grub menu.
|
grub-btrfs supports manual snapshots as well as snapper, timeshift, and yabsnap created snapshots.
|
||||||
Supports manual snapshots, snapper, timeshift ...
|
|
||||||
|
|
||||||
##### Warning: booting on read-only snapshots can be tricky
|
##### Warning: booting read-only snapshots can be tricky
|
||||||
|
|
||||||
If you choose to do it, `/var/log` or even `/var` must be on a separate subvolume.
|
If you wish to use read-only snapshots, `/var/log` or even `/var` must be on a separate subvolume.
|
||||||
Otherwise, make sure your snapshots are writeable.
|
Otherwise, make sure your snapshots are writable.
|
||||||
See [this ticket](https://github.com/Antynea/grub-btrfs/issues/92) for more info.
|
See [this ticket](https://github.com/Antynea/grub-btrfs/issues/92) for more info.
|
||||||
|
|
||||||
This project includes its own solution.
|
This project includes its own solution.
|
||||||
Refer to the [documentation](https://github.com/Antynea/grub-btrfs/blob/master/initramfs/readme.md).
|
Refer to the [documentation](https://github.com/Antynea/grub-btrfs/blob/master/initramfs/readme.md).
|
||||||
|
|
||||||
##
|
- - -
|
||||||
### What does grub-btrfs v4.xx do :
|
### ✨ What features does grub-btrfs have?
|
||||||
* Automatically List snapshots existing on root partition (btrfs).
|
* Automatically lists snapshots existing on the btrfs root partition.
|
||||||
* Automatically Detect if "/boot" is in separate partition.
|
* Automatically detect if `/boot` is in a separate partition.
|
||||||
* Automatically Detect kernel, initramfs and intel/amd microcode in "/boot" directory on snapshots.
|
* Automatically detect kernel, initramfs and Intel/AMD microcode in `/boot` directory within snapshots.
|
||||||
* Automatically Create corresponding "menuentry" in `grub.cfg`
|
* Automatically create corresponding menu entries in `grub.cfg`
|
||||||
* Automatically detect snapper and use snapper's snapshot description if available.
|
* Automatically detect the type/tags/triggers and descriptions/comments of Snapper/Timeshift/Yabsnap snapshots.
|
||||||
* Automatically generate `grub.cfg` if you use the provided systemd service.
|
* Automatically generate `grub.cfg` if you use the provided Systemd/ OpenRC service.
|
||||||
|
|
||||||
##
|
- - -
|
||||||
### Installation :
|
### 🛠️ Installation:
|
||||||
#### Arch Linux
|
#### Arch Linux
|
||||||
|
The package is available in the extra repository [grub-btrfs](https://archlinux.org/packages/extra/any/grub-btrfs/)
|
||||||
```
|
```
|
||||||
pacman -S grub-btrfs
|
pacman -S grub-btrfs
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Manual
|
#### Gentoo
|
||||||
|
grub-btrfs is only available in the Gentoo User Repository (GURU) and not in the official Gentoo repository.
|
||||||
|
If you have not activated the GURU yet, do so by running:
|
||||||
|
```
|
||||||
|
emerge -av app-eselect/eselect-repository
|
||||||
|
eselect repository enable guru
|
||||||
|
emaint sync -r guru
|
||||||
|
```
|
||||||
|
If you are using Systemd on Gentoo, make sure the USE-Flag `systemd` is set. (Either globally in make.conf or in package.use for the package app-backup/grub-btrfs)
|
||||||
|
Without Systemd USE-Flag the OpenRC-daemon of grub-btrfs will be installed.
|
||||||
|
|
||||||
* Run `make install` or look into Makefile for instructions on where to put each file.
|
Emerge grub-btrfs via
|
||||||
|
`emerge app-backup/grub-btrfs`
|
||||||
|
|
||||||
NOTE: Generate your Grub menu after installation for the changes to take effect.
|
#### Kali Linux
|
||||||
On Arch Linux use `grub-mkconfig -o /boot/grub/grub.cfg`.
|
[grub-btrfs](http://pkg.kali.org/pkg/grub-btrfs) is available in the Kali Linux repository and can be installed with:
|
||||||
|
```
|
||||||
|
apt install grub-btrfs
|
||||||
|
```
|
||||||
|
Booting into read-only snapshots is fully supported when choosing btrfs as the file system during a standard Kali Linux installation following [this walk-through](https://www.kali.org/docs/installation/btrfs/).
|
||||||
|
|
||||||
##
|
#### Manual installation
|
||||||
### Customization:
|
* Run `make install`
|
||||||
|
* Run `make help` to check what options are available.
|
||||||
|
* Dependencies:
|
||||||
|
* [btrfs-progs](https://archlinux.org/packages/core/x86_64/btrfs-progs/)
|
||||||
|
* [grub](https://archlinux.org/packages/core/x86_64/grub/)
|
||||||
|
* [bash >4](https://archlinux.org/packages/core/x86_64/bash/)
|
||||||
|
* [gawk](https://archlinux.org/packages/core/x86_64/gawk/)
|
||||||
|
* (only when using the grub-btrfsd daemon)[inotify-tools](https://archlinux.org/packages/extra/x86_64/inotify-tools/)
|
||||||
|
|
||||||
You have the possibility to modify many parameters in `/etc/default/grub-btrfs/config`.
|
- - -
|
||||||
See [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) for more information.
|
### 📚 Manual usage of grub-btrfs
|
||||||
|
To manually generate grub snapshot entries you can run `sudo /etc/grub.d/41_snapshots-btrfs` which updates `grub-btrfs.cfg`. You then need to regenerate the GRUB configuration by running one of the following commands:
|
||||||
|
|
||||||
##
|
* On **Arch Linux** or **Gentoo** use `grub-mkconfig -o /boot/grub/grub.cfg`.
|
||||||
### Automatically update grub
|
* On **Fedora** use `grub2-mkconfig -o /boot/grub2/grub.cfg`
|
||||||
If you would like Grub to automatically update when a snapshot is made or deleted:
|
* On **Debian and Ubuntu based** distributions `update-grub` is a script that runs `grub-mkconfig ...`
|
||||||
* Use `systemctl start/enable grub-btrfs.path`.
|
|
||||||
* `grub-btrfs.path` automatically (re)generates `grub.cfg` when a modification appears in `/.snapshots` folder (by default).
|
This process can be automated to occur whenever you create or delete snapshots but this process is slightly different depending upon your distributions choice on init system. See the relevant instructions for your init system below.
|
||||||
* If your snapshots aren't mounted in `/.snapshots`, you must modify the watch folder using `systemctl edit grub-btrfs.path`.
|
|
||||||
* For example: Timeshift mount its snapshots in `/run/timeshift/backup/timeshift-btrfs/snapshots` folder.
|
### ⚙️ Customization:
|
||||||
|
|
||||||
|
You have the possibility to modify many parameters in `/etc/default/grub-btrfs/config`.
|
||||||
|
For further information see [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) or `man grub-btrfs`
|
||||||
|
|
||||||
|
#### Warning:
|
||||||
|
Some file locations and command names differ from distribution to distribution. Initially the configuration is set up to work with Arch and Gentoo (and many other distributions) out of the box, which are using the `grub-mkconfig` command.
|
||||||
|
However Fedora, for example, uses a different command, `grub2-mkconfig`.
|
||||||
|
Edit the `GRUB_BTRFS_MKCONFIG` variable in `/etc/default/grub-btrfs/config` file to reflect this. (e.g. `GRUB_BTRFS_MKCONFIG=/sbin/grub2-mkconfig` for Fedora)
|
||||||
|
|
||||||
|
On most distributions, the grub installation resides in `/boot/grub`. If grub is installed in a different place, change the variable `GRUB_BTRFS_MKCONFIG` in the config file accordingly. For Fedora this is `GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"`. The command to check the grub scripts is different on some system, for Fedora it is `GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check`
|
||||||
|
|
||||||
|
#### Customization of the grub-btrfsd daemon
|
||||||
|
|
||||||
|
Grub-btrfs comes with a daemon script that automatically updates the grub menu when it sees a snapshot being created or deleted in a directory it is given via command line. You must install `inotify-tools` before you can use grub-btrfsd.
|
||||||
|
|
||||||
|
The daemon can be configured by passing different command line arguments to it.
|
||||||
|
The available arguments are:
|
||||||
|
* `SNAPSHOTS_DIRS`
|
||||||
|
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
|
||||||
|
E.g. for Snapper or Yabsnap this would be `/.snapshots`. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
|
||||||
|
This argument is not necessary to provide if `--timeshift-auto` is set.
|
||||||
|
* `-c / --no-color`
|
||||||
|
Disable colors in output.
|
||||||
|
* `-l / --log-file`
|
||||||
|
This arguments specifies a file where grub-btrfsd should write log messages.
|
||||||
|
* `-r / --recursive`
|
||||||
|
Watch the snapshots directory recursively
|
||||||
|
* `-s / --syslog`
|
||||||
|
* `-o / --timeshift-old`
|
||||||
|
Look for snapshots in `/run/timeshift/backup/timeshift-btrfs` instead of `/run/timeshift/$PID/backup/timeshift-btrfs.` This is to be used for Timeshift versions <22.06. You must also use `--timeshift-auto` if using this option.
|
||||||
|
* `-t / --timeshift-auto`
|
||||||
|
This is a flag to activate the auto-detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to `/run/timeshift/$PID/backup/timeshift-btrfs`. Where `$PID` is the process ID of the currently running Timeshift session. The PID changes every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument `SNAPSHOTS_DIRS` has no effect.
|
||||||
|
* `-v / --verbose`
|
||||||
|
Let the log of the daemon be more verbose
|
||||||
|
* `-h / --help`
|
||||||
|
Displays a short help message.
|
||||||
|
- - -
|
||||||
|
### 🪀 Automatically update grub upon snapshot creation or deletion
|
||||||
|
Grub-btrfsd is a daemon that watches the snapshot directory for you and updates the grub menu automatically every time a snapshot is created or deleted.
|
||||||
|
By default this daemon watches the directory `/.snapshots` for changes (creation or deletion of snapshots) and triggers the grub menu creation and re-installation of grub if any changes are noticed.
|
||||||
|
Therefore, if Snapper or Yabsnap is used with its default directory, the daemon can just be started and nothing needs to be configured. See the instructions below to configure grub-btrfsd for use with Timeshift or when using an alternative snapshots directory with Snapper/Yabsnap.
|
||||||
|
- - -
|
||||||
|
#### grub-btrfsd systemd instructions
|
||||||
|
To start the daemon run:
|
||||||
|
```bash
|
||||||
|
sudo systemctl start grub-btrfsd
|
||||||
|
```
|
||||||
|
|
||||||
|
To activate it during system startup, run:
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable grub-btrfsd
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 💼 Snapshots not in `/.snapshots` when using systemd
|
||||||
|
By default the daemon is watching the directory `/.snapshots`. If the daemon should watch a different directory, it can be edited with:
|
||||||
|
```bash
|
||||||
|
sudo systemctl edit --full grub-btrfsd
|
||||||
|
```
|
||||||
|
You need to edit the `/.snapshots` part in the line that says `ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots`.
|
||||||
|
This is what the file should look like afterwards:
|
||||||
|
``` bash
|
||||||
|
[Unit]
|
||||||
|
Description=Regenerate grub-btrfs.cfg
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
LogLevelMax=notice
|
||||||
|
# Set the possible paths for `grub-mkconfig`
|
||||||
|
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
|
# Load environment variables from the configuration
|
||||||
|
EnvironmentFile=/etc/default/grub-btrfs/config
|
||||||
|
# Start the daemon, usage of it is:
|
||||||
|
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
|
||||||
|
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
|
||||||
|
# Optional arguments:
|
||||||
|
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
|
||||||
|
# -o, --timeshift-old Activate for timeshift versions <22.06
|
||||||
|
# -l, --log-file Specify a logfile to write to
|
||||||
|
# -v, --verbose Let the log of the daemon be more verbose
|
||||||
|
# -s, --syslog Write to syslog
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
When done, the service should be restarted with:
|
||||||
|
``` bash
|
||||||
|
sudo systemctl restart grub-btrfsd
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 🌟 Using Timeshift with systemd
|
||||||
|
Newer Timeshift versions (>= 22.06) create a new directory named after their process ID in `/run/timeshift` every time they are started. The PID will be different every time.
|
||||||
|
Therefore the daemon cannot simply watch a directory. It monitors `/run/timeshift` and if a directory is created it gets Timeshifts current PID then watches a directory in that newly created directory from Timeshift.
|
||||||
|
To activate this mode of the daemon, `--timeshift-auto` must be passed to the daemon as a command line argument.
|
||||||
|
|
||||||
|
To pass `--timeshift-auto` to grub-btrfsd, the .service file of grub-btrfsd can be edited with
|
||||||
|
```bash
|
||||||
|
sudo systemctl edit --full grub-btrfsd
|
||||||
|
```
|
||||||
|
|
||||||
|
The line that contains:
|
||||||
|
```bash
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd /.snapshots --syslog
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Should be modified to read:
|
||||||
|
``` bash
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
|
||||||
|
```
|
||||||
|
|
||||||
|
The modified file should look like this:
|
||||||
|
``` bash
|
||||||
|
[Unit]
|
||||||
|
Description=Regenerate grub-btrfs.cfg
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
LogLevelMax=notice
|
||||||
|
# Set the possible paths for `grub-mkconfig`
|
||||||
|
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
|
# Load environment variables from the configuration
|
||||||
|
EnvironmentFile=/etc/default/grub-btrfs/config
|
||||||
|
# Start the daemon, usage of it is:
|
||||||
|
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
|
||||||
|
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
|
||||||
|
# Optional arguments:
|
||||||
|
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
|
||||||
|
# -l, --log-file Specify a logfile to write to
|
||||||
|
# -v, --verbose Let the log of the daemon be more verbose
|
||||||
|
# -s, --syslog Write to syslog
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using an older release of Timeshift (before 22.06), you also need to add `--timeshift-old` so that your ExecStart line would look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto --timeshift-old
|
||||||
|
```
|
||||||
|
|
||||||
|
When done, the service must be restarted with:
|
||||||
|
``` bash
|
||||||
|
sudo systemctl restart grub-btrfsd
|
||||||
|
```
|
||||||
|
|
||||||
|
Note:
|
||||||
|
You can view your change with `systemctl cat grub-btrfsd`.
|
||||||
|
To revert all the changes use `systemctl revert grub-btrfsd`.
|
||||||
|
|
||||||
|
- - -
|
||||||
|
#### grub-btrfsd OpenRC instructions
|
||||||
|
To start the daemon run:
|
||||||
|
```bash
|
||||||
|
sudo rc-service grub-btrfsd start
|
||||||
|
```
|
||||||
|
|
||||||
|
To activate it during system startup, run:
|
||||||
|
```bash
|
||||||
|
sudo rc-config add grub-btrfsd default
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 💼 Snapshots not in `/.snapshots` for OpenRC
|
||||||
|
By default the daemon is watching the directory `/.snapshots`. If the daemon should watch a different directory, it can be edited by passing different arguments to it.
|
||||||
|
Arguments are passed to grub-btrfsd via the file `/etc/conf.d/grub-btrfsd`.
|
||||||
|
The variable `snapshots` defines the path the daemon will monitor for snapshots.
|
||||||
|
|
||||||
|
After editing, the file should look like this:
|
||||||
|
``` bash
|
||||||
|
# Copyright 2022 Pascal Jaeger
|
||||||
|
# Distributed under the terms of the GNU General Public License v3
|
||||||
|
|
||||||
|
## Where to locate the root snapshots
|
||||||
|
snapshots="/.snapshots" # Snapper in the root directory
|
||||||
|
#snapshots="/run/timeshift/backup/timeshift-btrfs/snapshots" # Timeshift < v22.06
|
||||||
|
|
||||||
|
## Optional arguments to run with the daemon
|
||||||
|
# Append options to this like this:
|
||||||
|
# optional_args="--syslog --timeshift-auto --verbose"
|
||||||
|
# Possible options are:
|
||||||
|
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory for timeshift >= 22.06
|
||||||
|
# -o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)
|
||||||
|
# -l, --log-file Specify a logfile to write to
|
||||||
|
# -v, --verbose Let the log of the daemon be more verbose
|
||||||
|
# -s, --syslog Write to syslog
|
||||||
|
optional_args="--syslog"
|
||||||
|
```
|
||||||
|
|
||||||
|
After that, the daemon should be restarted with:
|
||||||
|
``` bash
|
||||||
|
sudo rc-service grub-btrfsd restart
|
||||||
|
```
|
||||||
|
|
||||||
|
- - -
|
||||||
|
### Troubleshooting
|
||||||
|
If you experience problems with grub-btrfs don't hesitate [to file an issue](https://github.com/Antynea/grub-btrfs/issues/new/choose).
|
||||||
|
|
||||||
|
#### What version of grub-btrfs am I running?
|
||||||
|
When requesting help or reporting bugs in grub-btrfs, please run:
|
||||||
|
``` bash
|
||||||
|
sudo /etc/grub.d/41_snapshots-btrfs --version
|
||||||
|
```
|
||||||
|
or
|
||||||
|
``` bash
|
||||||
|
sudo /usr/bin/grub-btrfsd --help
|
||||||
|
```
|
||||||
|
to get the currently running version of grub-btrfs and include this information in your ticket.
|
||||||
|
|
||||||
|
#### Running grub-btrfsd in verbose mode
|
||||||
|
If you have problems with the daemon, you can run it with the `--verbose`-flag. To do so you can run:
|
||||||
|
``` bash
|
||||||
|
sudo /usr/bin/grub-btrfsd --verbose --timeshift-auto` (for timeshift)
|
||||||
|
# or
|
||||||
|
sudo /usr/bin/grub-btrfsd /.snapshots --verbose` (for snapper/yabsnap)
|
||||||
|
```
|
||||||
|
Or pass `--verbose` to the daemon using the Systemd .service file or the OpenRC conf.d file respectively.
|
||||||
|
|
||||||
|
For additional information on the daemon and its arguments, run `grub-btrfsd -h` or `man grub-btrfsd`
|
||||||
|
|
||||||
|
- - -
|
||||||
|
### Development
|
||||||
|
Grub-btrfs uses a rudimentary system of automatic versioning to tell apart different commits. This is helpful when users report problems and it is not immediately clear what version they are using.
|
||||||
|
We therefore have the following script in `.git/hooks/pre-commit`:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "Doing pre commit hook with version bump"
|
||||||
|
version="$(git describe --tags --abbrev=0)-$(git rev-parse --abbrev-ref HEAD)-$(date -u -Iseconds)"
|
||||||
|
echo "New version is ${version}"
|
||||||
|
sed -i "s/GRUB_BTRFS_VERSION=.*/GRUB_BTRFS_VERSION=${version}/" config
|
||||||
|
git add config
|
||||||
|
```
|
||||||
|
|
||||||
|
This automatically sets the version in the `config`-file to `[lasttag]-[branch-name]-[current-date-in-UTC]`.
|
||||||
|
In order to create a Tag we don't want to have this long version. In this case we set the version manually in `config` and commit with `git commit --no-verify`. This avoids running the hook.
|
||||||
|
|
||||||
Use `systemctl edit grub-btrfs.path`.
|
|
||||||
Then wrote:
|
|
||||||
```
|
|
||||||
[Path]
|
|
||||||
PathModified=/run/timeshift/backup/timeshift-btrfs/snapshots
|
|
||||||
```
|
|
||||||
and finally save.
|
|
||||||
* You can view your change to `systemctl cat grub-btrfs.path`.
|
|
||||||
* To revert change use `systemctl revert grub-btrfs.path`.
|
|
||||||
##
|
|
||||||
### Special thanks for assistance and contributions
|
### Special thanks for assistance and contributions
|
||||||
* [maximbaz](https://github.com/maximbaz)
|
* [Maxim Baz](https://github.com/maximbaz)
|
||||||
|
* [Schievel1](https://github.com/Antynea/grub-btrfs/discussions/173#discussioncomment-1438790)
|
||||||
* [All contributors](https://github.com/Antynea/grub-btrfs/graphs/contributors)
|
* [All contributors](https://github.com/Antynea/grub-btrfs/graphs/contributors)
|
||||||
##
|
- - -
|
||||||
|
|||||||
95
config
95
config
@@ -1,5 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
|
||||||
|
GRUB_BTRFS_VERSION=4.13-fix-bashisms-2024-03-27T20:48:48+00:00
|
||||||
|
|
||||||
# Disable grub-btrfs.
|
# Disable grub-btrfs.
|
||||||
# Default: "false"
|
# Default: "false"
|
||||||
#GRUB_BTRFS_DISABLE="true"
|
#GRUB_BTRFS_DISABLE="true"
|
||||||
@@ -8,18 +11,10 @@
|
|||||||
# Default: "Use distribution information from /etc/os-release."
|
# Default: "Use distribution information from /etc/os-release."
|
||||||
#GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots"
|
#GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots"
|
||||||
|
|
||||||
# Add a name ahead your snapshots entries in the Grub menu.
|
|
||||||
# Default: "Snapshot:"
|
|
||||||
#GRUB_BTRFS_PREFIXENTRY="Snapshot:"
|
|
||||||
|
|
||||||
# Show full path snapshot or only name in the Grub menu, weird reaction with snapper.
|
|
||||||
# Default: "true"
|
|
||||||
#GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="false"
|
|
||||||
|
|
||||||
# Custom title.
|
# Custom title.
|
||||||
# shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available.
|
# Shows/Hides "date" "snapshot" "type" "description" in the Grub menu, custom order available.
|
||||||
# Default: "p/d/n"
|
# Default: ("date" "snapshot" "type" "description")
|
||||||
#GRUB_BTRFS_TITLE_FORMAT="p/d/n"
|
#GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")
|
||||||
|
|
||||||
# Limit the number of snapshots populated in the GRUB menu.
|
# Limit the number of snapshots populated in the GRUB menu.
|
||||||
# Default: "50"
|
# Default: "50"
|
||||||
@@ -54,6 +49,21 @@
|
|||||||
# Default: ("")
|
# Default: ("")
|
||||||
#GRUB_BTRFS_CUSTOM_MICROCODE=("custom-ucode.img" "custom-uc.img "custom_ucode.cpio")
|
#GRUB_BTRFS_CUSTOM_MICROCODE=("custom-ucode.img" "custom-uc.img "custom_ucode.cpio")
|
||||||
|
|
||||||
|
# Additional kernel command line parameters that should be passed to the kernel
|
||||||
|
# when booting a snapshot.
|
||||||
|
# For dracut based distros this could be useful to pass "rd.live.overlay.overlayfs=1"
|
||||||
|
# or "rd.live.overlay.readonly=1" to the Kernel for booting snapshots read only.
|
||||||
|
# Default: ""
|
||||||
|
#GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"
|
||||||
|
|
||||||
|
# Comma separated mount options to be used when booting a snapshot.
|
||||||
|
# They can be defined here as well as in the "/" line inside the respective snapshots'
|
||||||
|
# "/etc/fstab" files. Mount options found in both places are combined, and this variable
|
||||||
|
# takes priority over `fstab` entries.
|
||||||
|
# NB: Do NOT include "subvol=..." or "subvolid=..." here.
|
||||||
|
# Default: ""
|
||||||
|
#GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"
|
||||||
|
|
||||||
# Ignore specific path during run "grub-mkconfig".
|
# Ignore specific path during run "grub-mkconfig".
|
||||||
# Only exact paths are ignored.
|
# Only exact paths are ignored.
|
||||||
# e.g : if `specific path` = @, only `@` snapshot will be ignored.
|
# e.g : if `specific path` = @, only `@` snapshot will be ignored.
|
||||||
@@ -66,17 +76,29 @@ GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@")
|
|||||||
# Default: ("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
|
# Default: ("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
|
||||||
GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
|
GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
|
||||||
|
|
||||||
|
# Ignore specific type/tag of snapshot during run "grub-mkconfig".
|
||||||
|
# For snapper:
|
||||||
|
# Type = single, pre, post.
|
||||||
|
# For Timeshift:
|
||||||
|
# Tag = boot, ondemand, hourly, daily, weekly, monthly.
|
||||||
|
# For yabsnap:
|
||||||
|
# Trigger = S, I, U.
|
||||||
|
# Default: ("")
|
||||||
|
#GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("")
|
||||||
|
|
||||||
|
# Ignore specific description of snapshot during run "grub-mkconfig".
|
||||||
|
# e.g: timeline
|
||||||
|
# Default: ("")
|
||||||
|
#GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("")
|
||||||
|
|
||||||
# By default "grub-btrfs" automatically detects your boot partition,
|
# By default "grub-btrfs" automatically detects your boot partition,
|
||||||
# either located at the system root or on a separate partition,
|
# either located at the system root or on a separate partition or in a subvolume,
|
||||||
# but cannot detect if it is in a subvolume.
|
# Change to "true" if your boot partition isn't detected as separate.
|
||||||
# Change to "true" if you have a boot partition in a different subvolume.
|
|
||||||
# Default: "false"
|
# Default: "false"
|
||||||
#GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"
|
#GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"
|
||||||
|
|
||||||
# Location of the folder containing the "grub.cfg" file.
|
# Location of the folder containing the "grub.cfg" file.
|
||||||
# Use by grub-btrfs to save the file "grub-btrfs.cfg".
|
|
||||||
# Might be grub2 on some systems.
|
# Might be grub2 on some systems.
|
||||||
# For example, on Fedora with EFI : "/boot/efi/EFI/fedora"
|
|
||||||
# Default: "/boot/grub"
|
# Default: "/boot/grub"
|
||||||
#GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"
|
#GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"
|
||||||
|
|
||||||
@@ -85,16 +107,43 @@ GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/doc
|
|||||||
# Default: "/boot"
|
# Default: "/boot"
|
||||||
#GRUB_BTRFS_BOOT_DIRNAME="/boot"
|
#GRUB_BTRFS_BOOT_DIRNAME="/boot"
|
||||||
|
|
||||||
# Name/path of grub-mkconfig, use by "grub-btrfs.service"
|
# Location where grub-btrfs.cfg should be saved.
|
||||||
# Might be 'grub2-mkconfig' on some systems
|
# Some distributions (like OpenSuSE) store those files at the snapshot directory
|
||||||
|
# instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
# startup of the system.
|
||||||
|
# Default: $GRUB_BTRFS_GRUB_DIRNAME
|
||||||
|
#GRUB_BTRFS_GBTRFS_DIRNAME="/boot/grub"
|
||||||
|
|
||||||
|
# Location of the directory where Grub searches for the grub-btrfs.cfg file.
|
||||||
|
# Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
# instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
# startup of the system.
|
||||||
|
# Default: "\${prefix}" # This is a grub variable that resolves to where grub is
|
||||||
|
# installed. (like /boot/grub, /boot/efi/grub)
|
||||||
|
# NOTE: If variables of grub are used here (like ${prefix}) they need to be escaped
|
||||||
|
# with `\` before the `$`
|
||||||
|
#GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"
|
||||||
|
|
||||||
|
|
||||||
|
# Name/path of grub-mkconfig command, use by "grub-btrfs.service"
|
||||||
|
# Might be 'grub2-mkconfig' on some systems (Fedora ...)
|
||||||
|
# Default paths are /sbin:/bin:/usr/sbin:/usr/bin,
|
||||||
|
# if your path is missing, report it on the upstream project.
|
||||||
# For example, on Fedora : "/sbin/grub2-mkconfig"
|
# For example, on Fedora : "/sbin/grub2-mkconfig"
|
||||||
# Default: /usr/bin/grub-mkconfig
|
# You can use only name or full path.
|
||||||
|
# Default: grub-mkconfig
|
||||||
#GRUB_BTRFS_MKCONFIG=/usr/bin/grub2-mkconfig
|
#GRUB_BTRFS_MKCONFIG=/usr/bin/grub2-mkconfig
|
||||||
|
|
||||||
# Snapper
|
# Name of grub-script-check command, use by "grub-btrfs"
|
||||||
# Snapper's config name to use
|
# Might be 'grub2-script-check' on some systems (Fedora ...)
|
||||||
# Default: "root"
|
# For example, on Fedora : "grub2-script-check"
|
||||||
#GRUB_BTRFS_SNAPPER_CONFIG="root"
|
# Default: grub-script-check
|
||||||
|
#GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check
|
||||||
|
|
||||||
|
# Path of grub-mkconfig_lib file, use by "grub-btrfs"
|
||||||
|
# Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (Opensuse ...)
|
||||||
|
# Default: /usr/share/grub/grub-mkconfig_lib
|
||||||
|
#GRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub-mkconfig_lib
|
||||||
|
|
||||||
# Password protection management for submenu,snapshots
|
# Password protection management for submenu,snapshots
|
||||||
# Refer to the Grub documentation https://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation
|
# Refer to the Grub documentation https://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Monitors for new snapshots
|
|
||||||
|
|
||||||
[Path]
|
|
||||||
PathModified=/.snapshots
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=Regenerate grub-btrfs.cfg
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
# Set the possible paths for `grub-mkconfig`
|
|
||||||
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
|
|
||||||
# Load environment variables from the configuration
|
|
||||||
EnvironmentFile=/etc/default/grub-btrfs/config
|
|
||||||
# Regenerate just '/boot/grub/grub-btrfs.cfg' if it exists and is not empty, else regenerate the whole grub menu
|
|
||||||
ExecStart=/bin/bash -c 'if [ -s "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub-btrfs.cfg" ]; then /etc/grub.d/41_snapshots-btrfs; else ${GRUB_BTRFS_MKCONFIG:-/usr/bin/grub-mkconfig} -o ${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub.cfg; fi'
|
|
||||||
340
grub-btrfsd
Executable file
340
grub-btrfsd
Executable file
@@ -0,0 +1,340 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2023 Pascal Jaeger
|
||||||
|
# Distributed under the terms of the GNU General Public License v3
|
||||||
|
# Update GRUB when new BTRFS snapshots are created.
|
||||||
|
|
||||||
|
sighandler() {
|
||||||
|
trap '""' SIGINT SIGTERM
|
||||||
|
vlog "Parent $$: Received signal SIGINT/ SIGTERM"
|
||||||
|
kill 0
|
||||||
|
wait
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
setcolors() {
|
||||||
|
if [ "${1}" = true ]; then
|
||||||
|
GREEN=$'\033[0;32m'
|
||||||
|
RED=$'\033[0;31m'
|
||||||
|
CYAN=$'\033[;36m'
|
||||||
|
RESET=$'\033[0m'
|
||||||
|
fi
|
||||||
|
if [ "${1}" = false ]; then
|
||||||
|
GREEN=$'\033[0;0m'
|
||||||
|
RED=$'\033[0;0m'
|
||||||
|
CYAN=$'\033[;0m'
|
||||||
|
RESET=$'\033[0m'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_help() {
|
||||||
|
echo "${CYAN}[?] Usage:"
|
||||||
|
echo "${0##*/} [-h, --help] [-c, --no-color] [-l, --log-file LOG_FILE] [-r, --recursive] [-s, --syslog] [-t, --timeshift-auto] [-v, --verbose] SNAPSHOTS_DIRS"
|
||||||
|
echo
|
||||||
|
echo "SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto"
|
||||||
|
echo
|
||||||
|
echo "Optional arguments:"
|
||||||
|
echo "-c, --no-color Disable colors in output"
|
||||||
|
echo "-l, --log-file Specify a logfile to write to"
|
||||||
|
echo "-r, --recursive Watch snapshots directory recursively"
|
||||||
|
echo "-s, --syslog Write to syslog"
|
||||||
|
echo "-o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)"
|
||||||
|
echo "-t, --timeshift-auto Automatically detect Timeshifts snapshot directory"
|
||||||
|
echo "-v, --verbose Let the log of the daemon be more verbose"
|
||||||
|
echo "-h, --help Display this message"
|
||||||
|
echo
|
||||||
|
echo "Version ${GRUB_BTRFS_VERSION}${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "${2}"$1"${RESET}"
|
||||||
|
if [ ${syslog} = true ]; then
|
||||||
|
logger -p user.notice -t ${0##*/}"["$$"]" "$1"
|
||||||
|
fi
|
||||||
|
if [ ${#logfile} -gt 1 ]; then
|
||||||
|
echo "$(date) ${1}" >> "${logfile}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
vlog() {
|
||||||
|
if [ ${verbose} = true ]; then
|
||||||
|
echo "${2}"$1"${RESET}"
|
||||||
|
if [ ${syslog} = true ]; then
|
||||||
|
logger -p user.notice -t ${0##*/} "$1"
|
||||||
|
fi
|
||||||
|
if [ ${#logfile} -gt 1 ]; then
|
||||||
|
echo "$(date) ${1}" >> "${logfile}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
err() {
|
||||||
|
echo "${2}"${1}"${RESET}" >&2
|
||||||
|
if [ ${syslog} = true ]; then
|
||||||
|
logger -p user.error -t ${0##*/} "$1"
|
||||||
|
fi
|
||||||
|
if [ ${#logfile} -gt 1 ]; then
|
||||||
|
echo "$(date) error: ${1}" >> "${logfile}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_arguments() {
|
||||||
|
while getopts :l:ctvrsh-: opt; do
|
||||||
|
case "$opt" in
|
||||||
|
-)
|
||||||
|
case "${OPTARG}" in
|
||||||
|
no-color)
|
||||||
|
setcolors false
|
||||||
|
;;
|
||||||
|
log-file)
|
||||||
|
logfile="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
|
||||||
|
;;
|
||||||
|
timeshift-auto)
|
||||||
|
timeshift_auto=true
|
||||||
|
;;
|
||||||
|
timeshift-old)
|
||||||
|
timeshift_old=true
|
||||||
|
;;
|
||||||
|
verbose)
|
||||||
|
verbose=true
|
||||||
|
;;
|
||||||
|
recursive)
|
||||||
|
recursive=true
|
||||||
|
;;
|
||||||
|
syslog)
|
||||||
|
syslog=true
|
||||||
|
;;
|
||||||
|
help)
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
|
||||||
|
err "[!] Unknown option --${OPTARG}" "${RED}" >&2
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
print_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac;;
|
||||||
|
c)
|
||||||
|
setcolors false
|
||||||
|
;;
|
||||||
|
l)
|
||||||
|
logfile="${OPTARG}"
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
timeshift_auto=true
|
||||||
|
;;
|
||||||
|
o)
|
||||||
|
timeshift_old=true
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
verbose=true
|
||||||
|
;;
|
||||||
|
r)
|
||||||
|
recursive=true
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
syslog=true
|
||||||
|
;;
|
||||||
|
h)
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ "$OPTERR" = 1 ] || [ "${optspec:0:1}" = ":" ]; then
|
||||||
|
err "[!] Non-option argument: '-${OPTARG}'" "${RED}" >&2
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
print_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
checks() {
|
||||||
|
# check if inotify exists, see issue #227
|
||||||
|
if ! command -v inotifywait >/dev/null 2>&1; then
|
||||||
|
err "[!] inotifywait was not found, exiting. Is inotify-tools installed?" "${RED}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${timeshift_auto} = false ] && [ ${timeshift_old} = true ]; then
|
||||||
|
err "[!] Flag --timeshift-old requires flag --timeshift-auto" "${RED}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ ${timeshift_auto} = true ]; then
|
||||||
|
for snapdir in "${snapdirs[@]}"
|
||||||
|
do
|
||||||
|
if ! [ -d ${snapdir} ]; then
|
||||||
|
err "[!] No directory found at ${snapdir}" "${RED}" >&2
|
||||||
|
err "[!] Please specify a valid snapshot directory" "${RED}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
if [ ${#logfile} -gt 1 ]; then
|
||||||
|
touch "${logfile}"
|
||||||
|
echo "GRUB-BTRFSD log $(date)" >> "${logfile}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${verbose} = true ]; then
|
||||||
|
inotify_qiet_flag=""
|
||||||
|
else
|
||||||
|
inotify_qiet_flag=" -q -q "
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${recursive} = true ]; then
|
||||||
|
inotify_recursive_flag=" -r "
|
||||||
|
else
|
||||||
|
inotify_recursive_flag=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${timeshift_auto} = true ]; then
|
||||||
|
watchtime=15
|
||||||
|
[ -d /run/timeshift ] || mkdir /run/timeshift
|
||||||
|
else
|
||||||
|
watchtime=0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
create_grub_menu() {
|
||||||
|
# create the grub submenu of the whole grub menu, depending on whether the submenu already exists
|
||||||
|
# and gives feedback if it worked
|
||||||
|
if grep "snapshots-btrfs" "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}"/grub.cfg; then
|
||||||
|
if /etc/grub.d/41_snapshots-btrfs; then
|
||||||
|
log "Grub submenu recreated" "${GREEN}"
|
||||||
|
else
|
||||||
|
err "[!] Error during grub submenu creation (grub-btrfs error)" "${RED}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ${GRUB_BTRFS_MKCONFIG:-grub-mkconfig} -o "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}"/grub.cfg; then
|
||||||
|
log "Grub menu recreated" "${GREEN}"
|
||||||
|
else
|
||||||
|
err "[!] Error during grub menu creation (grub/ grub-btrfs error)" "${RED}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_snapshot_dir() {
|
||||||
|
# old timeshift has it's snapshot dir in a different location
|
||||||
|
if [ "${timeshift_old}" = true ]; then
|
||||||
|
snapdir="/run/timeshift/backup/timeshift-btrfs/snapshots"
|
||||||
|
else
|
||||||
|
snapdir="/run/timeshift/${timeshift_pid}/backup/timeshift-btrfs/snapshots"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon_function() {
|
||||||
|
trap 'vlog "$BASHPID: Received SIGINT/ SIGTERM"; exit 0' SIGINT SIGTERM
|
||||||
|
# start the actual daemon
|
||||||
|
snapdir=$1
|
||||||
|
vlog "Subdaemon function started, PID: $BASHPID" "${GREEN}"
|
||||||
|
vlog "${BASHPID}: Entering infinite while for $snapdir" "${GREEN}"
|
||||||
|
vlog "${BASHPID}: Snapshot dir watchtimeout: $watchtime"
|
||||||
|
while true; do
|
||||||
|
runs=false
|
||||||
|
if [ ${timeshift_auto} = true ] && ! [ "${timeshift_pid}" -gt 0 ] ; then
|
||||||
|
# watch the timeshift folder for a folder that is created when timeshift starts up
|
||||||
|
sleep 1 # for safety so the outer while is not going crazy
|
||||||
|
if [ "${timeshift_pid}" -eq -2 ]; then
|
||||||
|
log "${BASHPID}: detected timeshift shutdown"
|
||||||
|
fi
|
||||||
|
timeshift_pid=$(ps ax | awk '{sub(/.*\//, "", $5)} $5 ~ /timeshift/ {print $1}')
|
||||||
|
if [ "${#timeshift_pid}" -gt 0 ]; then
|
||||||
|
set_snapshot_dir
|
||||||
|
log "${BASHPID}: detected running Timeshift at daemon startup, PID is: $timeshift_pid"
|
||||||
|
vlog "${BASHPID}: new snapshots directory is $snapdir"
|
||||||
|
else
|
||||||
|
log "Watching /run/timeshift for timeshift to start"
|
||||||
|
inotifywait ${inotify_qiet_flag} -e create -e delete /run/timeshift && {
|
||||||
|
sleep 1
|
||||||
|
timeshift_pid=$(ps ax | awk '{sub(/.*\//, "", $5)} $5 ~ /timeshift/ {print $1}')
|
||||||
|
set_snapshot_dir
|
||||||
|
log "${BASHPID}: detected Timeshift startup, PID is: $timeshift_pid" "${CYAN}"
|
||||||
|
vlog "${BASHPID}: new snapshots directory is $snapdir" "${CYAN}"
|
||||||
|
(create_grub_menu) # create the grub menu once immediately in a forking process. Snapshots from commandline using timeshift --create need this
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
runs=false
|
||||||
|
else
|
||||||
|
while [ -d "$snapdir" ]; do
|
||||||
|
# watch the actual snapshots folder for a new snapshot or a deletion of a snapshot
|
||||||
|
if [ ${runs} = false ] && [ ${verbose} = false ]; then
|
||||||
|
log "${BASHPID}: Watching $snapdir for new snapshots..." "${CYAN}"
|
||||||
|
else
|
||||||
|
vlog "${BASHPID}: Watching $snapdir for new snapshots..." "${CYAN}"
|
||||||
|
fi
|
||||||
|
runs=true
|
||||||
|
inotifywait ${inotify_qiet_flag} ${inotify_recursive_flag} -e create -e delete -e unmount -t "$watchtime" "$snapdir" && {
|
||||||
|
log "${BASHPID}: Detected snapshot creation/ deletion, recreating Grub menu" "${CYAN}"
|
||||||
|
sleep 5
|
||||||
|
create_grub_menu
|
||||||
|
}
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
timeshift_pid=-2
|
||||||
|
fi
|
||||||
|
if ! [ ${timeshift_auto} = true ] && ! [ -d "${snapdir}" ] ; then # in case someone deletes the snapshots folder (in snapper mode) to prevent the while loop from going wild
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
# init
|
||||||
|
timeshift_pid=-1
|
||||||
|
watchtime=0
|
||||||
|
logfile=0
|
||||||
|
snapshots=-1
|
||||||
|
timeshift_auto=false
|
||||||
|
timeshift_old=false
|
||||||
|
verbose=false
|
||||||
|
syslog=false
|
||||||
|
recursive=false
|
||||||
|
trap sighandler SIGINT SIGTERM
|
||||||
|
|
||||||
|
setcolors true # normally we want colors
|
||||||
|
|
||||||
|
sysconfdir="/etc"
|
||||||
|
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
|
||||||
|
# source config file
|
||||||
|
[ -f "$grub_btrfs_config" ] && . "$grub_btrfs_config"
|
||||||
|
[ -f "${sysconfdir}/default/grub" ] && . "${sysconfdir}/default/grub"
|
||||||
|
|
||||||
|
parse_arguments "${@}"
|
||||||
|
shift $(( OPTIND - 1 ))
|
||||||
|
snapdirs=( "${@}" )
|
||||||
|
|
||||||
|
vlog "Arguments:"
|
||||||
|
vlog "Snapshot directories: ${snapdirs[*]}"
|
||||||
|
vlog "Timestift autodetection: $timeshift_auto"
|
||||||
|
vlog "Timeshift old: $timeshift_old"
|
||||||
|
vlog "Logfile: $logfile"
|
||||||
|
vlog "Recursive: $recursive"
|
||||||
|
|
||||||
|
checks
|
||||||
|
setup
|
||||||
|
|
||||||
|
log "grub-btrfsd starting up..." "${GREEN}"
|
||||||
|
|
||||||
|
if [ ${timeshift_auto} = true ] ; then
|
||||||
|
daemon_function "timeshift" &
|
||||||
|
else
|
||||||
|
# for all dirs that got passed to the script, start a new fork with that dir
|
||||||
|
for snapdir in "${snapdirs[@]}"
|
||||||
|
do
|
||||||
|
vlog "starting daemon watching $snapdir..."
|
||||||
|
daemon_function "${snapdir}" &
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
wait # wait for forks to finish, kill child forks if SIGTERM is sent
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main "${@}"
|
||||||
17
grub-btrfsd.confd
Normal file
17
grub-btrfsd.confd
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Copyright 2023 Pascal Jaeger
|
||||||
|
# Distributed under the terms of the GNU General Public License v3
|
||||||
|
|
||||||
|
## Where to locate the root snapshots
|
||||||
|
snapshots="/.snapshots" # Snapper in the root directory
|
||||||
|
#snapshots="/run/timeshift/backup/timeshift-btrfs/snapshots" # Timeshift < v22.06
|
||||||
|
|
||||||
|
## Optional arguments to run with the daemon
|
||||||
|
# Append options to this like this:
|
||||||
|
# optional_args="--syslog --timeshift-auto --verbose"
|
||||||
|
# Possible options are:
|
||||||
|
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory for timeshift >= 22.06
|
||||||
|
# -o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)
|
||||||
|
# -l, --log-file Specify a logfile to write to
|
||||||
|
# -v, --verbose Let the log of the daemon be more verbose
|
||||||
|
# -s, --syslog Write to syslog
|
||||||
|
optional_args="--syslog"
|
||||||
13
grub-btrfsd.initd
Executable file
13
grub-btrfsd.initd
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
# Copyright 2023 Pascal Jaeger
|
||||||
|
# Distributed under the terms of the GNU General Public License v3
|
||||||
|
|
||||||
|
name="grub-btrfs daemon"
|
||||||
|
command="/usr/bin/grub-btrfsd"
|
||||||
|
command_args="$optional_args ${snapshots}"
|
||||||
|
pidfile="/run/{RC_SVCNAME}.pid"
|
||||||
|
command_background=true
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
use localmount
|
||||||
|
}
|
||||||
23
grub-btrfsd.service
Normal file
23
grub-btrfsd.service
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Regenerate grub-btrfs.cfg
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
LogLevelMax=notice
|
||||||
|
# Set the possible paths for `grub-mkconfig`
|
||||||
|
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
|
# Load environment variables from the configuration
|
||||||
|
EnvironmentFile=/etc/default/grub-btrfs/config
|
||||||
|
# Start the daemon, usage of it is:
|
||||||
|
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
|
||||||
|
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
|
||||||
|
# Optional arguments:
|
||||||
|
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
|
||||||
|
# -o, --timeshift-old Activate for timeshift versions <22.06
|
||||||
|
# -l, --log-file Specify a logfile to write to
|
||||||
|
# -v, --verbose Let the log of the daemon be more verbose
|
||||||
|
# -s, --syslog Write to syslog
|
||||||
|
ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -39,7 +39,11 @@ You notice that the name of the `hook` must match the name of the 2 installed fi
|
|||||||
Re-generate your initramfs
|
Re-generate your initramfs
|
||||||
`mkinitcpio -P` (option -P means, all preset present in `/etc/mkinitcpio.d`)
|
`mkinitcpio -P` (option -P means, all preset present in `/etc/mkinitcpio.d`)
|
||||||
|
|
||||||
|
#### Dracut based distros
|
||||||
|
Distributions that use Dracut to make their initramfs (many of the Fedora based Distros) simply have to pass either `rd.live.overlay.readonly=1` (to boot into the snapshot read only) or `rd.live.overlay.overlayfs=1` (to act like a livedisk, that is files can be changed but changes will be lost on the next boot) to their kernel command line in grub.
|
||||||
|
Grub-btrfs provides the variable `GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS` to add any command to the kernel command line. Set it to `GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"` to make snapshots immutable when booted into.
|
||||||
|
After changing this run `sudo /etc/grub.d/41_snapshots-btrfs` to generate a new snapshot-submenu with the parameter added.
|
||||||
|
|
||||||
#### Other distribution
|
#### Other distribution
|
||||||
Refer to your distribution's documentation
|
Refer to your distribution's documentation or contribute to this project to add a paragraph.
|
||||||
or contribute to this project to add a paragraph.
|
|
||||||
#
|
#
|
||||||
|
|||||||
280
manpages/grub-btrfs.8.man
Normal file
280
manpages/grub-btrfs.8.man
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
.TH "grub-btrfs" "8"
|
||||||
|
|
||||||
|
.SH "NAME"
|
||||||
|
.PP
|
||||||
|
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
|
||||||
|
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
.PP
|
||||||
|
\fC/etc/grub.d/41_snapshots\-btrfs [\-V, \-\-version]\fP
|
||||||
|
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.PP
|
||||||
|
Improves grub by adding “btrfs snapshots” to the grub menu.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
You can boot your system on a “snapshot” from the grub menu.
|
||||||
|
Supports manual snapshots, snapper and timeshift.
|
||||||
|
Features of grub-btrfs:
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically list snapshots existing on root partition (btrfs).
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect if /boot is in separate partition.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect kernel, initramfs and intel/amd microcode in /boot directory on snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically create corresponding “menuentry” in grub.cfg
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically generate grub.cfg if you use the provided systemd service.
|
||||||
|
|
||||||
|
.SH "CONFIGURATION"
|
||||||
|
.PP
|
||||||
|
grub-btrfs is configured via the file \fC/etc/default/grub\-btrfs/config\fP.
|
||||||
|
Possible options are:
|
||||||
|
|
||||||
|
.SS "GENERAL"
|
||||||
|
.SS "\fCGRUB_BTRFS_DISABLE\fP"
|
||||||
|
.PP
|
||||||
|
Disable grub-btrfs if true.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_DISABLE="true"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_TITLE_FORMAT\fP"
|
||||||
|
.PP
|
||||||
|
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“date” “snapshot” “type” “description”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_LIMIT\fP"
|
||||||
|
.PP
|
||||||
|
Maximum number of snapshots in the GRUB snapshots sub menu.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “50”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_LIMIT="50"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SUBVOLUME_SORT\fP"
|
||||||
|
.PP
|
||||||
|
Sort the found subvolumes by “ogeneration” or “generation” or “path” or “rootid”.
|
||||||
|
.IP \(em 4
|
||||||
|
See Sorting section in
|
||||||
|
.BR btrfs-subvolume (8)
|
||||||
|
.PP
|
||||||
|
“-rootid” means list snapshot by new ones first.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “-rootid”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SUBVOLUME_SORT="+ogen,\-gen,path,rootid"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND\fP"
|
||||||
|
.PP
|
||||||
|
Show snapshots found during run “grub-mkconfig”
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “true”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_ROOTFLAGS\fP"
|
||||||
|
.PP
|
||||||
|
Comma separated mount options to be used when booting a snapshot.
|
||||||
|
They can be defined here as well as in the “/” line inside the respective snapshots’
|
||||||
|
“/etc/fstab” files. Mount options found in both places are combined, and this variable
|
||||||
|
takes priority over `fstab` entries.
|
||||||
|
NB: Do NOT include “subvol=...” or “subvolid=...” here.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION\fP"
|
||||||
|
.PP
|
||||||
|
By default “grub-btrfs” automatically detects your boot partition,
|
||||||
|
either located at the system root or on a separate partition or in a subvolume,
|
||||||
|
Change to “true” if your boot partition is not detected as separate.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"\fP
|
||||||
|
|
||||||
|
.SS "CUSTOM KERNELS"
|
||||||
|
.SS "\fCGRUB_BTRFS_NKERNEL\fP / \fCGRUB_BTRFS_NINIT\fP / \fCGRUB_BTRFS_CUSTOM_MICROCODE\fP"
|
||||||
|
.PP
|
||||||
|
By default, “grub-btrfs” automatically detects most existing kernels, initramfs and microcode.
|
||||||
|
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_NKERNEL=("kernel\-5.19.4\-custom" "vmlinux\-5.19.4\-custom")\fP
|
||||||
|
\fCGRUB_BTRFS_NINIT=("initramfs\-5.19.4\-custom.img" "initrd\-5.19.4\-custom.img" "otherinit\-5.19.4\-custom.gz")\fP
|
||||||
|
\fCGRUB_BTRFS_CUSTOM_MICROCODE=("custom\-ucode.img" "custom\-uc.img "custom_ucode.cpio")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS\fP"
|
||||||
|
.PP
|
||||||
|
Additional kernel command line parameters that should be passed to the kernelwhen
|
||||||
|
booting a snapshot.
|
||||||
|
For dracut based distros this could be useful to pass “rd.live.overlay.overlayfs=1”
|
||||||
|
or “rd.live.overlay.readonly=1” to the Kernel for booting read only snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"\fP
|
||||||
|
|
||||||
|
.SS "SNAPSHOT FILTERING"
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific path during run “grub-mkconfig”.
|
||||||
|
Only exact paths are ignored.
|
||||||
|
e.g : if `specific path` = @, only `@` snapshot will be ignored.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“@”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_PREFIX_PATH\fP"
|
||||||
|
.PP
|
||||||
|
Ignore prefix path during run “grub-mkconfig”.
|
||||||
|
Any path starting with the specified string will be ignored.
|
||||||
|
e.g : if `prefix path` = @, all snapshots beginning with “@/...” will be ignored.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“var/lib/docker” “@var/lib/docker” “@/var/lib/docker”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific type/tag of snapshot during run “grub-mkconfig”.
|
||||||
|
For snapper:
|
||||||
|
Type = single, pre, post.
|
||||||
|
For Timeshift:
|
||||||
|
Tag = boot, ondemand, hourly, daily, weekly, monthly.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific description of snapshot during run “grub-mkconfig”.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")\fP
|
||||||
|
|
||||||
|
.SS "DISTRIBUTION DEPENDENT SETTINGS"
|
||||||
|
.SS "\fCGRUB_BTRFS_BOOT_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of kernels/initramfs/microcode.
|
||||||
|
Used by “grub-btrfs” to detect the boot partition and the location of kernels, initramfs and microcodes.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “/boot”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_BOOT_DIRNAME="/"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GRUB_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of the folder containing the “grub.cfg” file.
|
||||||
|
Might be grub2 on some systems.
|
||||||
|
For example, on Fedora with EFI : “/boot/efi/EFI/fedora”
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “/boot/grub”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GBTRFS_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location where grub-btrfs.cfg should be saved.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: \fC$GRUB_BTRFS_GRUB_DIRNAME\fP
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of the directory where Grub searches for the grub-btrfs.cfg file.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “\${prefix}” (This is a grub variable that resolves to where grub is
|
||||||
|
.PP
|
||||||
|
installed. (like /boot/grub, /boot/efi/grub))
|
||||||
|
.IP \(em 4
|
||||||
|
NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
|
||||||
|
.PP
|
||||||
|
with `$\` before the `$`
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_MKCONFIG\fP"
|
||||||
|
.PP
|
||||||
|
Name/path of the command to generate the grub menu, used by “grub-btrfs.service”
|
||||||
|
Might be ’grub2-mkconfig’ on some systems (e.g. Fedora)
|
||||||
|
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
|
||||||
|
You can use the name of the command only or full the path.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: grub-mkconfig
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_MKCONFIG=/sbin/grub2\-mkconfig\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SCRIPT_CHECK\fP"
|
||||||
|
.PP
|
||||||
|
Name of grub-script-check command, used by “grub-btrfs”
|
||||||
|
Might be ’grub2-script-check’ on some systems (e.g. Fedora)
|
||||||
|
.IP \(em 4
|
||||||
|
Default: grub-script-check
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SCRIPT_CHECK=grub2\-script\-check\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_MKCONFIG_LIB\fP"
|
||||||
|
.PP
|
||||||
|
Path of grub-mkconfig\d\s-2lib\s+2\u file, used by “grub-btrfs”
|
||||||
|
Might be ’/usr/share/grub2/grub-mkconfig\d\s-2lib\s+2\u’ on some systems (e.g. Opensuse)
|
||||||
|
.IP \(em 4
|
||||||
|
Default: /usr/share/grub/grub-mkconfig\d\s-2lib\s+2\u
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub\-mkconfig_lib\fP
|
||||||
|
|
||||||
|
.SS "SECURITY"
|
||||||
|
.SS "\fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS\fP"
|
||||||
|
.PP
|
||||||
|
Password protection management for submenu, snapshots
|
||||||
|
Refer to the Grub documentation \fIhttps://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation\fP
|
||||||
|
and this comment \fIhttps://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660\fP
|
||||||
|
Add authorized usernames separate by comma (userfoo,userbar).
|
||||||
|
When Grub’s password protection is enabled, the superuser is authorized by default, it is not necessary to add it
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU\fP"
|
||||||
|
.PP
|
||||||
|
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
|
||||||
|
does not work if GRUB\d\s-2BTRFS\s+2\u\d\s-2PROTECTION\s+2\u\d\s-2AUTHORIZED\s+2\u\d\s-2USERS\s+2\u is not empty
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"\fP
|
||||||
|
|
||||||
|
.SH "FILES"
|
||||||
|
.PP
|
||||||
|
/etc/default/grub-btrfs/config
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
.PP
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
210
manpages/grub-btrfs.8.org
Normal file
210
manpages/grub-btrfs.8.org
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
#+title: grub-btrfs
|
||||||
|
#+author: Pascal Jaeger
|
||||||
|
#+MAN_CLASS_OPTIONS: :section-id "8"
|
||||||
|
|
||||||
|
* NAME
|
||||||
|
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
|
||||||
|
|
||||||
|
* SYNOPSIS
|
||||||
|
~/etc/grub.d/41_snapshots-btrfs [-V, --version]~
|
||||||
|
|
||||||
|
* DESCRIPTION
|
||||||
|
Improves grub by adding "btrfs snapshots" to the grub menu.
|
||||||
|
|
||||||
|
You can boot your system on a "snapshot" from the grub menu.
|
||||||
|
Supports manual snapshots, snapper and timeshift.
|
||||||
|
Features of grub-btrfs:
|
||||||
|
- Automatically list snapshots existing on root partition (btrfs).
|
||||||
|
- Automatically detect if /boot is in separate partition.
|
||||||
|
- Automatically detect kernel, initramfs and intel/amd microcode in /boot directory on snapshots.
|
||||||
|
- Automatically create corresponding "menuentry" in grub.cfg
|
||||||
|
- Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
|
||||||
|
- Automatically generate grub.cfg if you use the provided systemd service.
|
||||||
|
|
||||||
|
* CONFIGURATION
|
||||||
|
grub-btrfs is configured via the file ~/etc/default/grub-btrfs/config~.
|
||||||
|
Possible options are:
|
||||||
|
|
||||||
|
** GENERAL
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_DISABLE~
|
||||||
|
Disable grub-btrfs if true.
|
||||||
|
- Default: "false"
|
||||||
|
- Example: ~GRUB_BTRFS_DISABLE="true"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_TITLE_FORMAT~
|
||||||
|
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
|
||||||
|
- Default: ("date" "snapshot" "type" "description")
|
||||||
|
- Example: ~GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_LIMIT~
|
||||||
|
Maximum number of snapshots in the GRUB snapshots sub menu.
|
||||||
|
- Default: "50"
|
||||||
|
- Example: ~GRUB_BTRFS_LIMIT="50"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_SUBVOLUME_SORT~
|
||||||
|
Sort the found subvolumes by "ogeneration" or "generation" or "path" or "rootid".
|
||||||
|
- See Sorting section in
|
||||||
|
#+BEGIN_MAN
|
||||||
|
.BR btrfs-subvolume (8)
|
||||||
|
#+END_MAN
|
||||||
|
"-rootid" means list snapshot by new ones first.
|
||||||
|
- Default: "-rootid"
|
||||||
|
- Example: ~GRUB_BTRFS_SUBVOLUME_SORT="+ogen,-gen,path,rootid"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND~
|
||||||
|
Show snapshots found during run "grub-mkconfig"
|
||||||
|
- Default: "true"
|
||||||
|
- Example: ~GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_ROOTFLAGS~
|
||||||
|
Comma separated mount options to be used when booting a snapshot.
|
||||||
|
They can be defined here as well as in the "/" line inside the respective snapshots'
|
||||||
|
"/etc/fstab" files. Mount options found in both places are combined, and this variable
|
||||||
|
takes priority over `fstab` entries.
|
||||||
|
NB: Do NOT include "subvol=..." or "subvolid=..." here.
|
||||||
|
- Default: ""
|
||||||
|
- Example: ~GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION~
|
||||||
|
By default "grub-btrfs" automatically detects your boot partition,
|
||||||
|
either located at the system root or on a separate partition or in a subvolume,
|
||||||
|
Change to "true" if your boot partition is not detected as separate.
|
||||||
|
- Default: "false"
|
||||||
|
- Example: ~GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"~
|
||||||
|
|
||||||
|
** CUSTOM KERNELS
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_NKERNEL~ / ~GRUB_BTRFS_NINIT~ / ~GRUB_BTRFS_CUSTOM_MICROCODE~
|
||||||
|
By default, "grub-btrfs" automatically detects most existing kernels, initramfs and microcode.
|
||||||
|
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
|
||||||
|
- Default: ("")
|
||||||
|
- Example: ~GRUB_BTRFS_NKERNEL=("kernel-5.19.4-custom" "vmlinux-5.19.4-custom")~
|
||||||
|
~GRUB_BTRFS_NINIT=("initramfs-5.19.4-custom.img" "initrd-5.19.4-custom.img" "otherinit-5.19.4-custom.gz")~
|
||||||
|
~GRUB_BTRFS_CUSTOM_MICROCODE=("custom-ucode.img" "custom-uc.img "custom_ucode.cpio")~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS~
|
||||||
|
Additional kernel command line parameters that should be passed to the kernelwhen
|
||||||
|
booting a snapshot.
|
||||||
|
For dracut based distros this could be useful to pass "rd.live.overlay.overlayfs=1"
|
||||||
|
or "rd.live.overlay.readonly=1" to the Kernel for booting read only snapshots.
|
||||||
|
- Default: ""
|
||||||
|
- Example: ~GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"~
|
||||||
|
|
||||||
|
** SNAPSHOT FILTERING
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_IGNORE_SPECIFIC_PATH~
|
||||||
|
Ignore specific path during run "grub-mkconfig".
|
||||||
|
Only exact paths are ignored.
|
||||||
|
e.g : if `specific path` = @, only `@` snapshot will be ignored.
|
||||||
|
- Default: ("@")
|
||||||
|
- Example: ~GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_IGNORE_PREFIX_PATH~
|
||||||
|
Ignore prefix path during run "grub-mkconfig".
|
||||||
|
Any path starting with the specified string will be ignored.
|
||||||
|
e.g : if `prefix path` = @, all snapshots beginning with "@/..." will be ignored.
|
||||||
|
- Default: ("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
|
||||||
|
- Example: ~GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE~
|
||||||
|
Ignore specific type/tag of snapshot during run "grub-mkconfig".
|
||||||
|
For snapper:
|
||||||
|
Type = single, pre, post.
|
||||||
|
For Timeshift:
|
||||||
|
Tag = boot, ondemand, hourly, daily, weekly, monthly.
|
||||||
|
- Default: ("")
|
||||||
|
- Example: ~GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION~
|
||||||
|
Ignore specific description of snapshot during run "grub-mkconfig".
|
||||||
|
- Default: ("")
|
||||||
|
- Example: ~GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")~
|
||||||
|
|
||||||
|
** DISTRIBUTION DEPENDENT SETTINGS
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_BOOT_DIRNAME~
|
||||||
|
Location of kernels/initramfs/microcode.
|
||||||
|
Used by "grub-btrfs" to detect the boot partition and the location of kernels, initramfs and microcodes.
|
||||||
|
- Default: "/boot"
|
||||||
|
- Example: ~GRUB_BTRFS_BOOT_DIRNAME="/"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_GRUB_DIRNAME~
|
||||||
|
Location of the folder containing the "grub.cfg" file.
|
||||||
|
Might be grub2 on some systems.
|
||||||
|
For example, on Fedora with EFI : "/boot/efi/EFI/fedora"
|
||||||
|
- Default: "/boot/grub"
|
||||||
|
- Example: ~GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_GBTRFS_DIRNAME~
|
||||||
|
Location where grub-btrfs.cfg should be saved.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
- Default: ~$GRUB_BTRFS_GRUB_DIRNAME~
|
||||||
|
- Example: ~GRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME~
|
||||||
|
Location of the directory where Grub searches for the grub-btrfs.cfg file.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
- Default: "\${prefix}" (This is a grub variable that resolves to where grub is
|
||||||
|
installed. (like /boot/grub, /boot/efi/grub))
|
||||||
|
- NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
|
||||||
|
with `\` before the `$`
|
||||||
|
- Example: ~GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_MKCONFIG~
|
||||||
|
Name/path of the command to generate the grub menu, used by
|
||||||
|
#+BEGIN_MAN
|
||||||
|
.BR grub-btrfsd (8)
|
||||||
|
#+END_MAN
|
||||||
|
Might be 'grub2-mkconfig' on some systems (e.g. Fedora)
|
||||||
|
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
|
||||||
|
You can use the name of the command only or full the path.
|
||||||
|
- Default: grub-mkconfig
|
||||||
|
- Example: ~GRUB_BTRFS_MKCONFIG=/sbin/grub2-mkconfig~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_SCRIPT_CHECK~
|
||||||
|
Name of grub-script-check command, used by "grub-btrfs"
|
||||||
|
Might be 'grub2-script-check' on some systems (e.g. Fedora)
|
||||||
|
- Default: grub-script-check
|
||||||
|
- Example: ~GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_MKCONFIG_LIB~
|
||||||
|
Path of grub-mkconfig_lib file, used by "grub-btrfs"
|
||||||
|
Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (e.g. Opensuse)
|
||||||
|
- Default: /usr/share/grub/grub-mkconfig_lib
|
||||||
|
- Example: ~GRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub-mkconfig_lib~
|
||||||
|
|
||||||
|
** SECURITY
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS~
|
||||||
|
Password protection management for submenu, snapshots
|
||||||
|
Refer to the Grub documentation https://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation
|
||||||
|
and this comment https://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660
|
||||||
|
Add authorized usernames separate by comma (userfoo,userbar).
|
||||||
|
When Grub's password protection is enabled, the superuser is authorized by default, it is not necessary to add it
|
||||||
|
- Default: ""
|
||||||
|
- Example: ~GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"~
|
||||||
|
|
||||||
|
*** ~GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU~
|
||||||
|
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
|
||||||
|
does not work if GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS is not empty
|
||||||
|
- Default: "false"
|
||||||
|
- Example: ~GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"~
|
||||||
|
|
||||||
|
* FILES
|
||||||
|
/etc/default/grub-btrfs/config
|
||||||
|
|
||||||
|
* SEE ALSO
|
||||||
|
#+BEGIN_MAN
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
#+END_MAN
|
||||||
|
|
||||||
|
* COPYRIGHT
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
84
manpages/grub-btrfsd.8.man
Normal file
84
manpages/grub-btrfsd.8.man
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
.TH "grub-btrfsd" "8"
|
||||||
|
|
||||||
|
.SH "NAME"
|
||||||
|
.PP
|
||||||
|
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
|
||||||
|
.BR grub-btrfs (8)
|
||||||
|
.PP
|
||||||
|
when a new btrfs snapshot is created.
|
||||||
|
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
.PP
|
||||||
|
\fCgrub\-btrfsd [\-h, \-\-help] [\-c, \-\-no\-color] [\-l, \-\-log\-file LOG_FILE] [\-r, \-\-recursive] [\-s, \-\-syslog] [\-t, \-\-timeshift\-auto] [\-o, \-\-timeshift\-old] [\-v, \-\-verbose] SNAPSHOTS_DIRS\fP
|
||||||
|
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.PP
|
||||||
|
Grub-btrfsd is a shell script which is meant to be run as a daemon.
|
||||||
|
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or \fC/etc/grub.d/41_snapshots\-btrfs\fP (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
|
||||||
|
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.SS "\fCSNAPSHOTS_DIRS\fP"
|
||||||
|
.PP
|
||||||
|
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
|
||||||
|
E.g. for Snapper this would be \fC/.snapshots\fP. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
|
||||||
|
This argument is not necessary to provide if \fC\-\-timeshift\-auto\fP is set.
|
||||||
|
|
||||||
|
.SS "\fC\-c / \-\-no\-color\fP"
|
||||||
|
.PP
|
||||||
|
Disable colors in output.
|
||||||
|
|
||||||
|
.SS "\fC\-l / \-\-log\-file\fP"
|
||||||
|
.PP
|
||||||
|
This arguments specifies a file where grub-btrfsd should write log messages.
|
||||||
|
|
||||||
|
.SS "\fC\-r / \-\-recursive\fP"
|
||||||
|
.PP
|
||||||
|
Watch snapshot directory recursively
|
||||||
|
|
||||||
|
.SS "\fC\-s / \-\-syslog\fP"
|
||||||
|
.PP
|
||||||
|
Write to syslog
|
||||||
|
|
||||||
|
.SS "\fC\-t / \-\-timeshift\-auto\fP"
|
||||||
|
.PP
|
||||||
|
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. Where \fC$PID\fP is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument \fCSNAPSHOTS_DIRS\fP has no effect.
|
||||||
|
|
||||||
|
.SS "\fC\-o / \-\-timeshift\-old\fP"
|
||||||
|
.PP
|
||||||
|
Look for snapshots in \fC/run/timeshift/backup/timeshift\-btrfs\fP instead of \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. This is to be used for Timeshift versions <22.06.
|
||||||
|
|
||||||
|
.SS "\fC\-v / \-\-verbose\fP"
|
||||||
|
.PP
|
||||||
|
Let the log of the daemon be more verbose
|
||||||
|
|
||||||
|
.SS "\fC\-h / \-\-help\fP"
|
||||||
|
.PP
|
||||||
|
Displays a short help message.
|
||||||
|
|
||||||
|
.SH "CONFIGURATION"
|
||||||
|
.PP
|
||||||
|
The daemon is usually configured via the file \fC/etc/conf.d/grub\-btrfsd\fP on openrc-init systems and \fCsudo systemctl edit \-\-full grub\-btrfsd\fP on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
|
||||||
|
|
||||||
|
.SS "NOTES"
|
||||||
|
.PP
|
||||||
|
A common configuration for Snapper would be to set \fCSNAPSHOTS_DIR\fP to \fC/.snapshots\fP and not to set \fC\-\-timeshift\-auto\fP.
|
||||||
|
For Timeshift \fC\-\-timeshift\-auto\fP is set to true and \fCSNAPSHOTS_DIR\fP can be left as is.
|
||||||
|
|
||||||
|
.SH "FILES"
|
||||||
|
.PP
|
||||||
|
\fC/etc/conf.d/grub\-btrfsd\fP
|
||||||
|
\fC/usr/lib/systemd/system/grub\-btrfsd.service\fP
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
.IR inotifywait (1)
|
||||||
|
.IR openrc (8)
|
||||||
|
.IR rc-service (8)
|
||||||
|
.IR timeshift (1)
|
||||||
|
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
.PP
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
73
manpages/grub-btrfsd.8.org
Normal file
73
manpages/grub-btrfsd.8.org
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#+title: grub-btrfsd
|
||||||
|
#+author: Pascal Jaeger
|
||||||
|
#+MAN_CLASS_OPTIONS: :section-id "8"
|
||||||
|
|
||||||
|
* NAME
|
||||||
|
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
|
||||||
|
#+BEGIN_MAN
|
||||||
|
.BR grub-btrfs (8)
|
||||||
|
#+END_MAN
|
||||||
|
when a new btrfs snapshot is created.
|
||||||
|
|
||||||
|
* SYNOPSIS
|
||||||
|
~grub-btrfsd [-h, --help] [-c, --no-color] [-l, --log-file LOG_FILE] [-r, --recursive] [-s, --syslog] [-t, --timeshift-auto] [-o, --timeshift-old] [-v, --verbose] SNAPSHOTS_DIRS~
|
||||||
|
|
||||||
|
* DESCRIPTION
|
||||||
|
Grub-btrfsd is a shell script which is meant to be run as a daemon.
|
||||||
|
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or ~/etc/grub.d/41_snapshots-btrfs~ (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
|
||||||
|
|
||||||
|
* OPTIONS
|
||||||
|
** ~SNAPSHOTS_DIRS~
|
||||||
|
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
|
||||||
|
E.g. for Snapper this would be ~/.snapshots~. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
|
||||||
|
This argument is not necessary to provide if ~--timeshift-auto~ is set.
|
||||||
|
|
||||||
|
** ~-c / --no-color~
|
||||||
|
Disable colors in output.
|
||||||
|
|
||||||
|
** ~-l / --log-file~
|
||||||
|
This arguments specifies a file where grub-btrfsd should write log messages.
|
||||||
|
|
||||||
|
** ~-r / --recursive~
|
||||||
|
Watch snapshot directory recursively
|
||||||
|
|
||||||
|
** ~-s / --syslog~
|
||||||
|
Write to syslog
|
||||||
|
|
||||||
|
** ~-t / --timeshift-auto~
|
||||||
|
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to ~/run/timeshift/$PID/backup/timeshift-btrfs~. Where ~$PID~ is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument ~SNAPSHOTS_DIRS~ has no effect.
|
||||||
|
|
||||||
|
** ~-o / --timeshift-old~
|
||||||
|
Look for snapshots in ~/run/timeshift/backup/timeshift-btrfs~ instead of ~/run/timeshift/$PID/backup/timeshift-btrfs~. This is to be used for Timeshift versions <22.06.
|
||||||
|
|
||||||
|
** ~-v / --verbose~
|
||||||
|
Let the log of the daemon be more verbose
|
||||||
|
|
||||||
|
** ~-h / --help~
|
||||||
|
Displays a short help message.
|
||||||
|
|
||||||
|
* CONFIGURATION
|
||||||
|
The daemon is usually configured via the file ~/etc/conf.d/grub-btrfsd~ on openrc-init systems and ~sudo systemctl edit --full grub-btrfsd~ on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
|
||||||
|
|
||||||
|
** NOTES
|
||||||
|
A common configuration for Snapper would be to set ~SNAPSHOTS_DIR~ to ~/.snapshots~ and not to set ~--timeshift-auto~.
|
||||||
|
For Timeshift ~--timeshift-auto~ is set to true and ~SNAPSHOTS_DIR~ can be left as is.
|
||||||
|
|
||||||
|
* FILES
|
||||||
|
~/etc/conf.d/grub-btrfsd~
|
||||||
|
~/usr/lib/systemd/system/grub-btrfsd.service~
|
||||||
|
|
||||||
|
* SEE ALSO
|
||||||
|
#+BEGIN_MAN
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
.IR inotifywait (1)
|
||||||
|
.IR openrc (8)
|
||||||
|
.IR rc-service (8)
|
||||||
|
.IR timeshift (1)
|
||||||
|
#+END_MAN
|
||||||
|
|
||||||
|
* COPYRIGHT
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
280
temp/grub-btrfs.8
Normal file
280
temp/grub-btrfs.8
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
.TH "grub-btrfs" "8"
|
||||||
|
|
||||||
|
.SH "NAME"
|
||||||
|
.PP
|
||||||
|
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
|
||||||
|
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
.PP
|
||||||
|
\fC/etc/grub.d/41_snapshots\-btrfs [\-V, \-\-version]\fP
|
||||||
|
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.PP
|
||||||
|
Improves grub by adding “btrfs snapshots” to the grub menu.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
You can boot your system on a “snapshot” from the grub menu.
|
||||||
|
Supports manual snapshots, snapper and timeshift.
|
||||||
|
Features of grub-btrfs:
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically list snapshots existing on root partition (btrfs).
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect if /boot is in separate partition.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect kernel, initramfs and intel/amd microcode in /boot directory on snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically create corresponding “menuentry” in grub.cfg
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Automatically generate grub.cfg if you use the provided systemd service.
|
||||||
|
|
||||||
|
.SH "CONFIGURATION"
|
||||||
|
.PP
|
||||||
|
grub-btrfs is configured via the file \fC/etc/default/grub\-btrfs/config\fP.
|
||||||
|
Possible options are:
|
||||||
|
|
||||||
|
.SS "GENERAL"
|
||||||
|
.SS "\fCGRUB_BTRFS_DISABLE\fP"
|
||||||
|
.PP
|
||||||
|
Disable grub-btrfs if true.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_DISABLE="true"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_TITLE_FORMAT\fP"
|
||||||
|
.PP
|
||||||
|
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“date” “snapshot” “type” “description”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_LIMIT\fP"
|
||||||
|
.PP
|
||||||
|
Maximum number of snapshots in the GRUB snapshots sub menu.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “50”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_LIMIT="50"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SUBVOLUME_SORT\fP"
|
||||||
|
.PP
|
||||||
|
Sort the found subvolumes by “ogeneration” or “generation” or “path” or “rootid”.
|
||||||
|
.IP \(em 4
|
||||||
|
See Sorting section in
|
||||||
|
.BR btrfs-subvolume (8)
|
||||||
|
.PP
|
||||||
|
“-rootid” means list snapshot by new ones first.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “-rootid”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SUBVOLUME_SORT="+ogen,\-gen,path,rootid"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND\fP"
|
||||||
|
.PP
|
||||||
|
Show snapshots found during run “grub-mkconfig”
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “true”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_ROOTFLAGS\fP"
|
||||||
|
.PP
|
||||||
|
Comma separated mount options to be used when booting a snapshot.
|
||||||
|
They can be defined here as well as in the “/” line inside the respective snapshots’
|
||||||
|
“/etc/fstab” files. Mount options found in both places are combined, and this variable
|
||||||
|
takes priority over `fstab` entries.
|
||||||
|
NB: Do NOT include “subvol=...” or “subvolid=...” here.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION\fP"
|
||||||
|
.PP
|
||||||
|
By default “grub-btrfs” automatically detects your boot partition,
|
||||||
|
either located at the system root or on a separate partition or in a subvolume,
|
||||||
|
Change to “true” if your boot partition is not detected as separate.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"\fP
|
||||||
|
|
||||||
|
.SS "CUSTOM KERNELS"
|
||||||
|
.SS "\fCGRUB_BTRFS_NKERNEL\fP / \fCGRUB_BTRFS_NINIT\fP / \fCGRUB_BTRFS_CUSTOM_MICROCODE\fP"
|
||||||
|
.PP
|
||||||
|
By default, “grub-btrfs” automatically detects most existing kernels, initramfs and microcode.
|
||||||
|
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_NKERNEL=("kernel\-5.19.4\-custom" "vmlinux\-5.19.4\-custom")\fP
|
||||||
|
\fCGRUB_BTRFS_NINIT=("initramfs\-5.19.4\-custom.img" "initrd\-5.19.4\-custom.img" "otherinit\-5.19.4\-custom.gz")\fP
|
||||||
|
\fCGRUB_BTRFS_CUSTOM_MICROCODE=("custom\-ucode.img" "custom\-uc.img "custom_ucode.cpio")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS\fP"
|
||||||
|
.PP
|
||||||
|
Additional kernel command line parameters that should be passed to the kernelwhen
|
||||||
|
booting a snapshot.
|
||||||
|
For dracut based distros this could be useful to pass “rd.live.overlay.overlayfs=1”
|
||||||
|
or “rd.live.overlay.readonly=1” to the Kernel for booting read only snapshots.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"\fP
|
||||||
|
|
||||||
|
.SS "SNAPSHOT FILTERING"
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific path during run “grub-mkconfig”.
|
||||||
|
Only exact paths are ignored.
|
||||||
|
e.g : if `specific path` = @, only `@` snapshot will be ignored.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“@”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_PREFIX_PATH\fP"
|
||||||
|
.PP
|
||||||
|
Ignore prefix path during run “grub-mkconfig”.
|
||||||
|
Any path starting with the specified string will be ignored.
|
||||||
|
e.g : if `prefix path` = @, all snapshots beginning with “@/...” will be ignored.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“var/lib/docker” “@var/lib/docker” “@/var/lib/docker”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific type/tag of snapshot during run “grub-mkconfig”.
|
||||||
|
For snapper:
|
||||||
|
Type = single, pre, post.
|
||||||
|
For Timeshift:
|
||||||
|
Tag = boot, ondemand, hourly, daily, weekly, monthly.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION\fP"
|
||||||
|
.PP
|
||||||
|
Ignore specific description of snapshot during run “grub-mkconfig”.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: (“”)
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")\fP
|
||||||
|
|
||||||
|
.SS "DISTRIBUTION DEPENDENT SETTINGS"
|
||||||
|
.SS "\fCGRUB_BTRFS_BOOT_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of kernels/initramfs/microcode.
|
||||||
|
Used by “grub-btrfs” to detect the boot partition and the location of kernels, initramfs and microcodes.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “/boot”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_BOOT_DIRNAME="/"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GRUB_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of the folder containing the “grub.cfg” file.
|
||||||
|
Might be grub2 on some systems.
|
||||||
|
For example, on Fedora with EFI : “/boot/efi/EFI/fedora”
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “/boot/grub”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GBTRFS_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location where grub-btrfs.cfg should be saved.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: \fC$GRUB_BTRFS_GRUB_DIRNAME\fP
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME\fP"
|
||||||
|
.PP
|
||||||
|
Location of the directory where Grub searches for the grub-btrfs.cfg file.
|
||||||
|
Some distributions (like OpenSuSE) store those file at the snapshot directory
|
||||||
|
instead of boot. Be aware that this directory must be available for grub during
|
||||||
|
startup of the system.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “\${prefix}” (This is a grub variable that resolves to where grub is
|
||||||
|
.PP
|
||||||
|
installed. (like /boot/grub, /boot/efi/grub))
|
||||||
|
.IP \(em 4
|
||||||
|
NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
|
||||||
|
.PP
|
||||||
|
with `$\` before the `$`
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_MKCONFIG\fP"
|
||||||
|
.PP
|
||||||
|
Name/path of the command to generate the grub menu, used by “grub-btrfs.service”
|
||||||
|
Might be ’grub2-mkconfig’ on some systems (e.g. Fedora)
|
||||||
|
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
|
||||||
|
You can use the name of the command only or full the path.
|
||||||
|
.IP \(em 4
|
||||||
|
Default: grub-mkconfig
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_MKCONFIG=/sbin/grub2\-mkconfig\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_SCRIPT_CHECK\fP"
|
||||||
|
.PP
|
||||||
|
Name of grub-script-check command, used by “grub-btrfs”
|
||||||
|
Might be ’grub2-script-check’ on some systems (e.g. Fedora)
|
||||||
|
.IP \(em 4
|
||||||
|
Default: grub-script-check
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_SCRIPT_CHECK=grub2\-script\-check\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_MKCONFIG_LIB\fP"
|
||||||
|
.PP
|
||||||
|
Path of grub-mkconfig\d\s-2lib\s+2\u file, used by “grub-btrfs”
|
||||||
|
Might be ’/usr/share/grub2/grub-mkconfig\d\s-2lib\s+2\u’ on some systems (e.g. Opensuse)
|
||||||
|
.IP \(em 4
|
||||||
|
Default: /usr/share/grub/grub-mkconfig\d\s-2lib\s+2\u
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub\-mkconfig_lib\fP
|
||||||
|
|
||||||
|
.SS "SECURITY"
|
||||||
|
.SS "\fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS\fP"
|
||||||
|
.PP
|
||||||
|
Password protection management for submenu, snapshots
|
||||||
|
Refer to the Grub documentation \fIhttps://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation\fP
|
||||||
|
and this comment \fIhttps://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660\fP
|
||||||
|
Add authorized usernames separate by comma (userfoo,userbar).
|
||||||
|
When Grub’s password protection is enabled, the superuser is authorized by default, it is not necessary to add it
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"\fP
|
||||||
|
|
||||||
|
.SS "\fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU\fP"
|
||||||
|
.PP
|
||||||
|
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
|
||||||
|
does not work if GRUB\d\s-2BTRFS\s+2\u\d\s-2PROTECTION\s+2\u\d\s-2AUTHORIZED\s+2\u\d\s-2USERS\s+2\u is not empty
|
||||||
|
.IP \(em 4
|
||||||
|
Default: “false”
|
||||||
|
.IP \(em 4
|
||||||
|
Example: \fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"\fP
|
||||||
|
|
||||||
|
.SH "FILES"
|
||||||
|
.PP
|
||||||
|
/etc/default/grub-btrfs/config
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
.PP
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
84
temp/grub-btrfsd.8
Normal file
84
temp/grub-btrfsd.8
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
.TH "grub-btrfsd" "8"
|
||||||
|
|
||||||
|
.SH "NAME"
|
||||||
|
.PP
|
||||||
|
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
|
||||||
|
.BR grub-btrfs (8)
|
||||||
|
.PP
|
||||||
|
when a new btrfs snapshot is created.
|
||||||
|
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
.PP
|
||||||
|
\fCgrub\-btrfsd [\-h, \-\-help] [\-c, \-\-no\-color] [\-l, \-\-log\-file LOG_FILE] [\-r, \-\-recursive] [\-s, \-\-syslog] [\-t, \-\-timeshift\-auto] [\-o, \-\-timeshift\-old] [\-v, \-\-verbose] SNAPSHOTS_DIRS\fP
|
||||||
|
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.PP
|
||||||
|
Grub-btrfsd is a shell script which is meant to be run as a daemon.
|
||||||
|
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or \fC/etc/grub.d/41_snapshots\-btrfs\fP (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
|
||||||
|
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.SS "\fCSNAPSHOTS_DIRS\fP"
|
||||||
|
.PP
|
||||||
|
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
|
||||||
|
E.g. for Snapper this would be \fC/.snapshots\fP. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
|
||||||
|
This argument is not necessary to provide if \fC\-\-timeshift\-auto\fP is set.
|
||||||
|
|
||||||
|
.SS "\fC\-c / \-\-no\-color\fP"
|
||||||
|
.PP
|
||||||
|
Disable colors in output.
|
||||||
|
|
||||||
|
.SS "\fC\-l / \-\-log\-file\fP"
|
||||||
|
.PP
|
||||||
|
This arguments specifies a file where grub-btrfsd should write log messages.
|
||||||
|
|
||||||
|
.SS "\fC\-r / \-\-recursive\fP"
|
||||||
|
.PP
|
||||||
|
Watch snapshot directory recursively
|
||||||
|
|
||||||
|
.SS "\fC\-s / \-\-syslog\fP"
|
||||||
|
.PP
|
||||||
|
Write to syslog
|
||||||
|
|
||||||
|
.SS "\fC\-t / \-\-timeshift\-auto\fP"
|
||||||
|
.PP
|
||||||
|
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. Where \fC$PID\fP is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument \fCSNAPSHOTS_DIRS\fP has no effect.
|
||||||
|
|
||||||
|
.SS "\fC\-o / \-\-timeshift\-old\fP"
|
||||||
|
.PP
|
||||||
|
Look for snapshots in \fC/run/timeshift/backup/timeshift\-btrfs\fP instead of \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. This is to be used for Timeshift versions <22.06.
|
||||||
|
|
||||||
|
.SS "\fC\-v / \-\-verbose\fP"
|
||||||
|
.PP
|
||||||
|
Let the log of the daemon be more verbose
|
||||||
|
|
||||||
|
.SS "\fC\-h / \-\-help\fP"
|
||||||
|
.PP
|
||||||
|
Displays a short help message.
|
||||||
|
|
||||||
|
.SH "CONFIGURATION"
|
||||||
|
.PP
|
||||||
|
The daemon is usually configured via the file \fC/etc/conf.d/grub\-btrfsd\fP on openrc-init systems and \fCsudo systemctl edit \-\-full grub\-btrfsd\fP on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
|
||||||
|
|
||||||
|
.SS "NOTES"
|
||||||
|
.PP
|
||||||
|
A common configuration for Snapper would be to set \fCSNAPSHOTS_DIR\fP to \fC/.snapshots\fP and not to set \fC\-\-timeshift\-auto\fP.
|
||||||
|
For Timeshift \fC\-\-timeshift\-auto\fP is set to true and \fCSNAPSHOTS_DIR\fP can be left as is.
|
||||||
|
|
||||||
|
.SH "FILES"
|
||||||
|
.PP
|
||||||
|
\fC/etc/conf.d/grub\-btrfsd\fP
|
||||||
|
\fC/usr/lib/systemd/system/grub\-btrfsd.service\fP
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.IR btrfs (8)
|
||||||
|
.IR btrfs-subvolume (8)
|
||||||
|
.IR grub-btrfsd (8)
|
||||||
|
.IR grub-mkconfig (8)
|
||||||
|
.IR inotifywait (1)
|
||||||
|
.IR openrc (8)
|
||||||
|
.IR rc-service (8)
|
||||||
|
.IR timeshift (1)
|
||||||
|
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
.PP
|
||||||
|
Copyright (c) 2022 Pascal Jäger
|
||||||
Reference in New Issue
Block a user