Compare commits

..

27 Commits

Author SHA1 Message Date
Antynea
2054eb53d9 Correct typo 2021-11-26 17:22:27 +01:00
Antynea
7ba2c59030 Update Readme
* Update Description section:
Adds experimental method for booting to a snapshot in read-only mode with systemd.

* Update Installation section:
Adds : Run make help to check what options are available.
Adds new dependency: strings
2021-11-26 17:20:26 +01:00
Antynea
208c679ac5 Add "GRUB_BTRFS_SYSTEMD_VOLATILE" option 2021-11-26 16:55:53 +01:00
Antynea
b2a3a2343c Add systemd-volatile
Adds support for "systemd.volatile=state" only.
See: https://github.com/Antynea/grub-btrfs/issues/92#issuecomment-966869223

"GRUB_BTRFS_SYSTEMD_VOLATILE" must be true.
The default init on the snapshot should be "systemd".
The snapshot must have the tag "ro=true".
2021-11-26 16:47:04 +01:00
Antynea
ee3c366fa4 Add missing initrd (#184) 2021-11-26 02:49:37 +01:00
Antynea
4f1aa38604 Make path of "grub-mkconfig_lib" configurable (#181)
* Make path of "grub-mkconfig_lib" configurable

  * 41_snapshots-btrfs file:
    - Remove "datarootdir" variable, is no longer used
    - Replace "$datarootdir/grub/grub-mkconfig_lib" with "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}"

  * Config file:
    - Adds new GRUB_BTRFS_MKCONFIG_LIB variable
Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (Opensuse ...)
2021-11-17 19:30:34 +01:00
Antynea
1accd5e272 Make name of "grub-script-check" configurable (#177)
41_snapshots-btrfs file:
  * Remove "grub_script_check" variable

Config file;
  * Make name of "grub-script-check" configurable
    * Might be 'grub2-script-check' on some systems (Fedora ...)
2021-11-07 14:35:17 +01:00
Antynea
2500ce8d30 Fix broken Makefile:
* Remove empty lines.
  * Adds missing double quote.
  * Deleted files differ from installed files:
    * Installed files:
      - "$(BIN_DIR)/" grub-btrfs-openrc;
      - "$(DESTDIR)/etc/init.d/" grub-btrfsd;

    * Deleted files:
      - "$(BIN_DIR)/grub-btrfs.openrcbin";
      - "$(DESTDIR)/etc/init.d/grub-btrfs.openrc";

    * Replace deleted files with:
      - "$(BIN_DIR)/grub-btrfs-openrc;"
      - "$(DESTDIR)/etc/init.d/grub-btrfsd;"
2021-11-07 13:55:18 +01:00
Antynea
d9f54afcb7 Update Installation section:
Update Dependencies
2021-11-04 12:26:23 +01:00
Antynea
33ad3273d3 * trim trailing whitespace.
* snapshot_list function:
  * Rename some variables for better consistency.
  * Remove unused variables.
  * Ignore snapper/timeshift snapshot as soon as possible.
2021-11-02 17:42:28 +01:00
Pascal Jäger
3b0d0c4ff7 changed makefile so it doesnt intefere with arch package build process 2021-11-02 16:18:04 +01:00
Pascal Jäger
66a218356a changed instruction for openrc local service 2021-11-02 16:18:04 +01:00
Pascal Jäger
7dc240faa7 Updated readme to take openRC daemon into consideration 2021-11-02 16:18:04 +01:00
Pascal Jäger
75e6408510 Added openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
fbc33391cb Added openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
63c3493504 Added a openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
02b925e4b5 Added an openRC daemon 2021-11-02 16:18:04 +01:00
Antynea
9d436adf95 Reworks many things (#174)
#### Script:
* Snapper:
  - Now, the information is retrieved from the info.xml file.

* Timeshift:
  * Now, the information is retrieved from the info.json file.

* Probe informations from device:
  * Add the UUID of the root and boot subvolumes

* Show full path snapshot or only name:
  * Remove, this feature never worked correctly

* Grub-menu:
  * Now displays the following information in separate columns:
    - Date of snapshot
    - Path of snapshot
    - Type/Tags of snapshot if available (snapper/timeshift)
    - Description/Comments of snapshot if available (snapper/timeshift)
  * Possibility to display only the desired information(s) (see config file)
  *  Adds a header for the column title
  * GRUB_BTRFS_PREFIXENTRY is remove

  * Boot partition detection:
    * grub-btrfs is now able to detect if the boot folder/partition is a subvolume
    * GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION should no longer be needed for this case

  * Variables:
    * Rename some variables

  * Header:
    * Update the header to reflect the changes.

#### Config:
* GRUB_BTRFS_PREFIXENTRY:
  * Remove, no longer use

* GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:
  * Remove, no longer use

* GRUB_BTRFS_TITLE_FORMAT:
  * Shows/Hides "date" "snapshot" "type" "description" in the Grub menu, custom order available.
    Default: ("date" "snapshot" "type" "description")

* GRUB_BTRFS_IGNORE_SNAPPER_TYPE:
  * Rename to GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE
    - Supports both timeshift and snapper tags/type

* GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION:
  * Rename to GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION
    - Supports both snapper and timeshift description/comments

* GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION:
  * grub-btrfs is now able to detect if the boot folder/partition is a subvolume.
  Activating this parameter should no longer be necessary for this case.

* GRUB_BTRFS_SNAPPER_CONFIG:
  * Remove, no longer use

#### Readme:
* Update "What does grub-btrfs v4.xx do" section
  * Adds support for timeshift
2021-10-25 15:47:26 +02:00
Antynea
301752f300 Update count_limit_snap arithmetic
* Update count_limit_snap arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:59:08 +02:00
Antynea
3b857348cb Update wait_max arithmetic
* Update wait_max arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:54:11 +02:00
Antynea
f3d8e99cb8 Update count_warning_menuentries arithmetic
* Update count_warning_menuentries arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:50:51 +02:00
Antynea
af80fe7993 Comments unused variables
* Comments unused variables:
  * This "$prefix_i" and "$suffix_i" are for information purposes only, and aren't used.
2021-10-21 16:44:59 +02:00
Antynea
c7f403d2a2 Update "GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU"
* Update "GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU":
  * Remove default parameter (false), not needed
  * adds automatic conversion of the value to lower case
2021-10-21 16:39:17 +02:00
Antynea
e6898c0de8 Update disable_script function
* Update disable_script function:
  * A function is no longer required since the commands have been moved to the beginning of the script.
2021-10-21 16:36:12 +02:00
Antynea
a790ff054e "disable_script" function breaks "grub-mkconfig"
* "disable_script" function breaks "grub-mkconfig":
  * Replace "return 1" by "exit 0".
2021-10-07 17:31:45 +02:00
Antynea
df643361cc Add Gentoo and OpenRC instructions
* Add Gentoo instructions in "Installation :" section.
* Add OpenRC instructions in "Automatically update grub :" section
2021-10-07 16:52:44 +02:00
Antynea
b0408225c1 Fix bug Create entries with matching version (#170)
* Fix #169 
  * Create entries with matching version doesn't work properly:
  Adds missing "else continue;"
2021-09-26 19:05:02 +02:00
6 changed files with 349 additions and 276 deletions

434
41_snapshots-btrfs Executable file → Normal file
View File

@@ -16,7 +16,7 @@
# - Automatically Detect if "/boot" is in separate partition. # - Automatically Detect if "/boot" is in 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 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:
@@ -36,7 +36,6 @@
set -e set -e
datarootdir="/usr/share"
sysconfdir="/etc" sysconfdir="/etc"
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config" grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
@@ -44,38 +43,38 @@ grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
[[ -f "${sysconfdir}/default/grub" ]] && . "${sysconfdir}/default/grub" [[ -f "${sysconfdir}/default/grub" ]] && . "${sysconfdir}/default/grub"
## Exit the script, if: ## Exit the script, if:
disable_script() { [[ "${GRUB_BTRFS_DISABLE,,}" == "true" ]] && exit 0 # Disable Grub-btrfs is set to true (default=false)
# Disable Grub-btrfs is set to true (default=false) if ! type btrfs >/dev/null 2>&1; then exit 0; fi # btrfs-progs isn't installed
[[ "${GRUB_BTRFS_DISABLE:-"false"}" == "true" ]] && return 1 [[ -f "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" ]] && . "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" || exit 0 # grub-mkconfig_lib couldn't be found
# btrfs-progs isn't installed # Root filesystem isn't btrfs
if ! type btrfs >/dev/null 2>&1; then return 1; fi root_fs=$(${grub_probe} --target="fs" / 2>/dev/null)
# grub-mkconfig_lib couldn't be found [[ "$root_fs" != "btrfs" ]] && exit 0
[[ -f "$datarootdir/grub/grub-mkconfig_lib" ]] && . "$datarootdir/grub/grub-mkconfig_lib" || return 1
# Root filesystem isn't btrfs ## Error Handling
root_fs=$(${grub_probe} --target="fs" / 2>/dev/null) print_error()
[[ "$root_fs" != "btrfs" ]] && return 1 {
return 0 local err_msg="$*"
local 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
} }
disable_script
printf "Detecting snapshots ...\n" >&2 ;
## 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)
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"} submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"}
## Prefix entry
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"}
## Limit snapshots to show in the Grub menu (default=50) ## Limit snapshots to show in the Grub menu (default=50)
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"}
## 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 "${GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU,,}" in
true) unrestricted_access_submenu="--unrestricted ";; true) unrestricted_access_submenu="--unrestricted ";;
*) unrestricted_access_submenu="" *) unrestricted_access_submenu=""
esac esac
@@ -88,16 +87,20 @@ fi
# Probe info "Root partition" # Probe info "Root partition"
root_device=$(${grub_probe} --target=device /) # Root device root_device=$(${grub_probe} --target=device /) # Root device
root_uuid=$(${grub_probe} --device ${root_device} --target="fs_uuid" 2>/dev/null) # UUID of the root device root_uuid=$(${grub_probe} --device ${root_device} --target="fs_uuid" 2>/dev/null) # UUID of the root device
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
root_uuid_subvolume=$(awk -F":" 'match($1, /(^[ \t]+UUID)/) {sub(/^[ \t]+/, "", $2); print $2}' <<< "$root_uuid_subvolume") # UUID of the root subvolume
# Probe info "Boot partition" # Probe info "Boot partition"
boot_device=$(${grub_probe} --target=device ${boot_directory}) # Boot device boot_device=$(${grub_probe} --target=device ${boot_directory}) # Boot device
boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null) # UUID of the boot device boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null) # UUID of the boot device
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}' <<< "$boot_uuid_subvolume") # UUID of the boot subvolume
boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null) # hints string boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null) # hints string
boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null) # Type filesystem of boot device 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"
## Mount point location ## Mount point location
gbgmp=$(mktemp -dt grub-btrfs.XXXXXXXXXX) 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
@@ -115,36 +118,25 @@ fi
## Detect rootflags ## Detect rootflags
detect_rootflags() detect_rootflags()
{ {
local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${gbgmp}/${snap_dir_name}/etc/fstab" \ local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${grub_btrfs_mount_point}/${snap_dir_name_trim}/etc/fstab" \
| sed -E 's/^.*[[:space:]]([[:graph:]]+)$/\1/;s/,?subvol(id)?=[^,$]+//g;s/^,//') | sed -E 's/^.*[[:space:]]([[:graph:]]+)$/\1/;s/,?subvol(id)?=[^,$]+//g;s/^,//')
rootflags="rootflags=${fstabflags:+$fstabflags,}${GRUB_BTRFS_ROOTFLAGS:+$GRUB_BTRFS_ROOTFLAGS,}" rootflags="rootflags=${fstabflags:+$fstabflags,}${GRUB_BTRFS_ROOTFLAGS:+$GRUB_BTRFS_ROOTFLAGS,}"
} }
## Path to grub-script-check
grub_script_check="${bindir}/grub-script-check"
## Error Handling unmount_grub_btrfs_mount_point()
print_error()
{ {
local err_msg="$*" if [[ -d "$grub_btrfs_mount_point" ]]; then
local 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
}
unmount_gbgmp()
{
if [[ -d "$gbgmp" ]]; then
local wait=true local wait=true
local wait_max=0 local wait_max=0
printf "Unmount %s .." "$gbgmp" >&2; printf "Unmount %s .." "$grub_btrfs_mount_point" >&2;
while $wait; do while $wait; do
if grep -qs "$gbgmp" /proc/mounts; then if grep -qs "$grub_btrfs_mount_point" /proc/mounts; then
wait_max=$((1+$wait_max)) wait_max=$((1+wait_max))
if umount "$gbgmp" >/dev/null 2>&1; then if umount "$grub_btrfs_mount_point" >/dev/null 2>&1; then
wait=false # umount successful wait=false # umount successful
printf " Success\n" >&2; printf " Success\n" >&2;
elif [[ $wait_max = 10 ]]; then elif [[ $wait_max = 10 ]]; then
printf "\nWarning: Unable to unmount %s in %s\n" "$root_device" "$gbgmp" >&2; printf "\nWarning: Unable to unmount %s in %s\n" "$root_device" "$grub_btrfs_mount_point" >&2;
break; break;
else else
printf "." >&2 ; # output to show that the script is alive printf "." >&2 ; # output to show that the script is alive
@@ -156,8 +148,8 @@ if [[ -d "$gbgmp" ]]; then
fi fi
done done
if [[ "$wait" != true ]]; then if [[ "$wait" != true ]]; then
if ! rm -d "$gbgmp" >/dev/null 2>&1; then if ! rm -d "$grub_btrfs_mount_point" >/dev/null 2>&1; then
printf "Unable to delete %s: Device or ressource is busy\n" "$gbgmp" >&2; printf "Unable to delete %s: Device or ressource is busy\n" "$grub_btrfs_mount_point" >&2;
fi fi
fi fi
fi fi
@@ -170,31 +162,40 @@ echo "$@" >> "$grub_directory/grub-btrfs.new"
} }
## menu entries ## menu entries
old_kernel_parameters=${kernel_parameters}
make_menu_entries() make_menu_entries()
{ {
kernel_parameters="${old_kernel_parameters}"
if [[ "${GRUB_BTRFS_SYSTEMD_VOLATILE}" == true ]] ; then
if [[ $(strings -n7 "$grub_btrfs_mount_point/$snap_dir_name_trim/usr/bin/init" | grep -aEiom1 'upstart|systemd|sysvinit') == systemd ]] \
|| [[ $(strings -n7 "$grub_btrfs_mount_point/$snap_dir_name_trim/sbin/init" | grep -aEiom1 'upstart|systemd|sysvinit') == systemd ]]; then
[[ $(btrfs property get "$grub_btrfs_mount_point/$snap_dir_name_trim" ro) != "ro=false" ]] && kernel_parameters="${kernel_parameters} systemd.volatile=state";
fi
fi
## \" 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
if [[ "${name_initramfs}" != "x" ]] ; then if [[ "${name_initramfs}" != "x" ]] ; then
prefix_i=${i%%"-"*} # prefix_i=${i%%"-"*}
suffix_i=${i#*"-"} suffix_i=${i#*"-"}
alt_suffix_i=${i##*"-"} # alt_suffix_i=${i##*"-"}
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}"; if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
else continue;
fi fi
for u in "${name_microcode[@]}"; do for u in "${name_microcode[@]}"; do
if [[ "${name_microcode}" != "x" ]] ; then if [[ "${name_microcode}" != "x" ]] ; then
entry " entry "
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {" menuentry ' "${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else else
entry " entry "
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {" menuentry ' "${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
fi fi
entry "\ entry "\
if [ x\$feature_all_video_module = xy ]; then if [ x\$feature_all_video_module = xy ]; then
@@ -207,9 +208,9 @@ 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}" ${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}" ...'
@@ -220,16 +221,16 @@ make_menu_entries()
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 else
for u in "${name_microcode[@]}"; do for u in "${name_microcode[@]}"; do
if [[ "${name_microcode}" != "x" ]] ; then if [[ "${name_microcode}" != "x" ]] ; then
entry " entry "
menuentry '"${k}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {" menuentry ' "${k}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else else
entry " entry "
menuentry '"${k}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {" menuentry ' "${k}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
fi fi
entry "\ entry "\
if [ x\$feature_all_video_module = xy ]; then if [ x\$feature_all_video_module = xy ]; then
@@ -242,16 +243,16 @@ 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}" ${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: "${u}" ...' echo 'Loading Microcode: "${u}" ...'
initrd \"${boot_dir_root_grub}/"${u}"\"" initrd \"${boot_dir_root_grub}/"${u}"\""
fi fi
entry " }" entry " }"
count_warning_menuentries=$((1+$count_warning_menuentries)) count_warning_menuentries=$((1+count_warning_menuentries))
done done
fi fi
done done
@@ -270,109 +271,117 @@ trim() {
## List of snapshots on filesystem ## List of snapshots on filesystem
snapshot_list() snapshot_list()
{ {
# Query info from snapper if it is installed local snapper_info="info.xml"
if type snapper >/dev/null 2>&1; then local timeshift_info="info.json"
if [ -s "/etc/snapper/configs/$snapper_config" ]; then local date_snapshots=()
printf "Info: snapper detected, using config: %s\n" "$snapper_config" >&2 local path_snapshots=()
local snapper_ids=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 1)) local type_snapshots=()
local snapper_types=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 2)) local description_snapshots=()
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: %s does not exist\n" "$snapper_config" >&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 [ -n "${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 [ -n "${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 informations
local type_snapshot="N/A"
local description_snapshot="N/A"
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"
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]}")
# ignore snapper_type or snapper_description during run "grub-mkconfig"
if [ -n "${GRUB_BTRFS_IGNORE_SNAPPER_TYPE}" ] ; then
for ist in ${GRUB_BTRFS_IGNORE_SNAPPER_TYPE[@]} ; do
[[ "${snapper_type}" == "${ist}" ]] && continue 3;
done
fi
if [ -n "${GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION}" ] ; then
for isd in ${GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION[@]} ; do
[[ "${snapper_description}" == "${isd}" ]] && continue 3;
done
fi
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")"
snap_snapshot="$snap_dir_name" # Used by "title_format" function
snap_type="$(echo "$item" | cut -d'|' -f3)" # column_3
snap_description="$(echo "$item" | cut -d'|' -f4)" # column_4
}
## Detect kernels in "boot_directory"
detect_kernel() detect_kernel()
{ {
list_kernel=() list_kernel=()
@@ -384,7 +393,7 @@ detect_kernel()
list_kernel+=("$okernel") list_kernel+=("$okernel")
done done
# Custom name kernel in GRUB_BTRFS_NKERNEL # Custom name kernel in "GRUB_BTRFS_NKERNEL"
if [ -n "${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;
@@ -393,21 +402,19 @@ detect_kernel()
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 \
"${boot_dir}"/initramfs-*.gz ; do
[[ ! -f "${oinitramfs}" ]] && continue; [[ ! -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 [ -n "${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;
@@ -417,7 +424,7 @@ detect_initramfs()
if [ -z "${list_initramfs}" ]; then list_initramfs=(x); 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=()
@@ -433,7 +440,7 @@ detect_microcode()
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 [ -n "${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
@@ -443,29 +450,39 @@ detect_microcode()
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}" title_menu+="${var}|"
esac title_submenu+=" $(trim "${var}") |"
done
}
# Adds a header to the grub-btrfs.cfg file
header_menu()
{
local 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_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
@@ -476,39 +493,25 @@ boot_bounded()
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
name_kernel=("${list_kernel[@]##*"/"}") name_kernel=("${list_kernel[@]##*"/"}")
# Detect rootflags
detect_rootflags
# Initramfs (Original + custom initramfs)
detect_initramfs detect_initramfs
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
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; [[ $count_limit_snap -ge $limit_snap_show ]] && break;
done done
IFS=$oldIFS IFS=$oldIFS
@@ -517,17 +520,12 @@ boot_bounded()
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
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[@]##*"/"}")
@@ -536,56 +534,33 @@ boot_separate()
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)"
snap_dir_name="$(trim "$snap_dir_name")"
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")"
# Detect rootflags
detect_rootflags detect_rootflags
title_format
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
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;
done done
IFS=$oldIFS IFS=$oldIFS
} }
printf "Detecting snapshots ...\n" >&2 ;
rm -f "$grub_directory/grub-btrfs.new" rm -f "$grub_directory/grub-btrfs.new"
> "$grub_directory/grub-btrfs.new" > "$grub_directory/grub-btrfs.new" # Create a "grub-btrfs.new" file in "grub_directory"
# 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 ro,subvolid=5 /dev/disk/by-uuid/"$root_uuid" "$gbgmp/" mount -o ro,subvolid=5 /dev/disk/by-uuid/"$root_uuid" "$grub_btrfs_mount_point/"
trap "unmount_gbgmp" EXIT # unmounting mount point on EXIT signal trap "unmount_grub_btrfs_mount_point" EXIT # unmounting mount point on EXIT signal
# Count menuentries count_warning_menuentries=0 # Count menuentries
count_warning_menuentries=0 count_limit_snap=0 # Count snapshots
# 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 [[ "${GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION,,}" == "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
# Show warn, menuentries exceeds 250 entries # 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 ; [[ $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 # Show total found snapshots
@@ -597,7 +572,8 @@ if [[ "${count_limit_snap}" = "0" || -z "${count_limit_snap}" ]]; then
print_error "No snapshots found." print_error "No snapshots found."
fi fi
# Make a submenu in GRUB (grub.cfg) and move "grub-btrfs.new" to "grub-btrfs.cfg" # Make a submenu in GRUB (grub.cfg) and move "grub-btrfs.new" to "grub-btrfs.cfg"
if ${grub_script_check} "$grub_directory/grub-btrfs.new"; then header_menu
if "${bindir}/${GRUB_BTRFS_SCRIPT_CHECK:-grub-script-check}" "$grub_directory/grub-btrfs.new"; then
cat "$grub_directory/grub-btrfs.new" > "$grub_directory/grub-btrfs.cfg" cat "$grub_directory/grub-btrfs.new" > "$grub_directory/grub-btrfs.cfg"
rm -f "$grub_directory/grub-btrfs.new" rm -f "$grub_directory/grub-btrfs.new"
cat << EOF cat << EOF

View File

@@ -2,9 +2,12 @@ PKGNAME ?= grub-btrfs
PREFIX ?= /usr PREFIX ?= /usr
INITCPIO ?= false INITCPIO ?= false
SYSTEMD ?= true
OPENRC ?= false
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
.PHONY: install uninstall help .PHONY: install uninstall help
@@ -15,14 +18,22 @@ install:
fi 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 @# Systemd init system
@install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.path @if test "$(SYSTEMD)" = true; then \
@install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.path; \
install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.service; \
fi
@# OpenRC init system
@if test "$(OPENRC)" = true; then \
install -Dm744 -t "$(BIN_DIR)/" grub-btrfs-openrc; \
install -Dm744 -t "$(DESTDIR)/etc/init.d/" grub-btrfsd; \
fi
@# Arch Linux like distros only : @# Arch Linux like distros only :
@if test "$(INITCPIO)" = true; then \ @if test "$(INITCPIO)" = true; then \
install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-install" "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"; \ 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"; \ install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-hook" "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"; \
fi fi
@install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE
@install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md @install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md
@install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md" @install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
@@ -35,8 +46,10 @@ uninstall:
rm -f "$${grub_dirname:-/boot/grub}/grub-btrfs.cfg" rm -f "$${grub_dirname:-/boot/grub}/grub-btrfs.cfg"
@rm -f "$(DESTDIR)/etc/default/grub-btrfs/config" @rm -f "$(DESTDIR)/etc/default/grub-btrfs/config"
@rm -f "$(DESTDIR)/etc/grub.d/41_snapshots-btrfs" @rm -f "$(DESTDIR)/etc/grub.d/41_snapshots-btrfs"
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.service"
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.path" @rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.path"
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.service"
@rm -f "$(BIN_DIR)/grub-btrfs-openrc;"
@rm -f "$(DESTDIR)/etc/init.d/grub-btrfsd;"
@rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs" @rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"
@rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs" @rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"
@# Arch Linux UNlike distros only : @# Arch Linux UNlike distros only :
@@ -68,4 +81,6 @@ help:
@echo " LIB_DIR | path | system libraries location | '\$$(DESTDIR)\$$(PREFIX)/lib'" @echo " LIB_DIR | path | system libraries location | '\$$(DESTDIR)\$$(PREFIX)/lib'"
@echo " PKGNAME | name | name of the ditributed package | 'grub-btrfs'" @echo " PKGNAME | name | name of the ditributed package | 'grub-btrfs'"
@echo " INITCPIO | bool | include mkinitcpio hook | false" @echo " INITCPIO | bool | include mkinitcpio hook | false"
@echo @echo " SYSTEMD | bool | include unit files | true"
@echo " OPENRC | bool | include OpenRc daemon | false"
@echo

View File

@@ -1,11 +1,11 @@
[![GitHub release](https://img.shields.io/github/release/Antynea/grub-btrfs.svg)](https://github.com/Antynea/grub-btrfs/releases) [![GitHub release](https://img.shields.io/github/release/Antynea/grub-btrfs.svg)](https://github.com/Antynea/grub-btrfs/releases)
![](https://img.shields.io/github/license/Antynea/grub-btrfs.svg) ![](https://img.shields.io/github/license/Antynea/grub-btrfs.svg)
## grub-btrfs ## grub-btrfs
This is a version 4.xx of 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. Improves Grub by adding "btrfs snapshots" to the Grub menu.
@@ -19,18 +19,18 @@ Otherwise, make sure your snapshots are writeable.
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).
* Or used `GRUB_BTRFS_SYSTEMD_VOLATILE=true` in config file. (experimental, See [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) for more information.)
## - - -
### What does grub-btrfs v4.xx do : ### What does grub-btrfs v4.xx do :
* 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/amd 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 :
#### Arch Linux #### Arch Linux
The package is available in the community repository [grub-btrfs](https://archlinux.org/packages/community/any/grub-btrfs/) The package is available in the community repository [grub-btrfs](https://archlinux.org/packages/community/any/grub-btrfs/)
@@ -38,25 +38,44 @@ The package is available in the community repository [grub-btrfs](https://archli
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
emerge --sync
```
Now merge grub-btrfs via
`emerge app-backup/grub-btrfs`
#### Manual
* Run `make install` or look into Makefile for instructions on where to put each file. * Run `make install` or look into Makefile for instructions on where to put each file.
* Run `make help` to check what options are available.
* Dependencies: * Dependencies:
* [btrfs-progs](https://archlinux.org/packages/core/x86_64/btrfs-progs/) * [btrfs-progs](https://archlinux.org/packages/core/x86_64/btrfs-progs/)
* [grub](https://archlinux.org/packages/core/x86_64/grub/) * [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/)
* [strings](https://archlinux.org/packages/core/x86_64/binutils/)
NOTE: Generate your Grub menu after installation for the changes to take effect. #### NOTE: All distros
On Arch Linux use `grub-mkconfig -o /boot/grub/grub.cfg`. Generate your Grub menu after installation for the changes to take effect.
On Debian-like distribution `update-grub` is an alias to `grub-mkconfig ...` For example:
## On **Arch Linux** or **Gentoo** use `grub-mkconfig -o /boot/grub/grub.cfg`.
On **Fedora** use `grub2-mkconfig -o /boot/grub2/grub.cfg`
On **Debian-like** distribution `update-grub` is an alias to `grub-mkconfig ...`
- - -
### Customization : ### Customization :
You have the possibility to modify many parameters in `/etc/default/grub-btrfs/config`. 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. See [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) for more information.
## - - -
### Automatically update grub ### Automatically update grub :
1- If you would like grub-btrfs menu to automatically update when a snapshot is created or deleted: #### Systemd
1. If you would like grub-btrfs menu to automatically update when a snapshot is created or deleted:
* Use `systemctl enable grub-btrfs.path`. * Use `systemctl enable grub-btrfs.path`.
* `grub-btrfs.path` automatically (re)generates `grub-btrfs.cfg` when a modification appears in `/.snapshots` mount point (by default). * `grub-btrfs.path` automatically (re)generates `grub-btrfs.cfg` when a modification appears in `/.snapshots` mount point (by default).
* If the `/.snapshots` mount point is already mounted, then use `systemctl start grub-btrfs.path` to start monitoring. * If the `/.snapshots` mount point is already mounted, then use `systemctl start grub-btrfs.path` to start monitoring.
@@ -91,15 +110,47 @@ use `systemctl list-units -t mount`.
* You can view your change to `systemctl cat grub-btrfs.path`. * You can view your change to `systemctl cat grub-btrfs.path`.
* To revert change use `systemctl revert grub-btrfs.path`. * To revert change use `systemctl revert grub-btrfs.path`.
2- If you would like grub-btrfs menu to automatically update on system restart/shutdown: 2. If you would like grub-btrfs menu to automatically update on system restart/ shutdown:
[Look at this comment](https://github.com/Antynea/grub-btrfs/issues/138#issuecomment-766918328) [Look at this comment](https://github.com/Antynea/grub-btrfs/issues/138#issuecomment-766918328)
Currently not implemented Currently not implemented
##
#### OpenRC
1. If you would like grub-btrfs menu to automatically update when a snapshot is created or deleted:
* Use `rc-config add grub-btrfsd default`, to start the grub-btrfsd daemon the next time the system boots.
* To start `grub-btrfsd` right now, run `rc-service grub-btrfsd start`
* `grub-btrfsd` automatically watches the snapshot directory of timeshift (/run/timeshift/backup/timeshift-btrfs/snapshots)
and updates the grub-menu when a change occurs.
* Currently untested for snapper
2. If you would like grub-btrfs menu to automatically update on system restart/ shutdown:
Just add the following script as `/etc/local.d/grub-btrfs-update.stop`
```
#!/bin/bash
description="Update the grub btrfs snapshots menu"
name="grub-btrfs-update"
depend()
{
use localmount
}
bash -c 'if [ -s "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub-btrfs.cfg" ]; then /etc/grub.d/41_snapshots-btrfs; else {GRUB_BTRFS_MKCONFIG:-grub-mkconfig} -o {GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub.cfg; fi'
```
Make your script executeable with `chmod a+x /etc/local.d/grub-btrfs-update.stop`.
* The extension ".stop" at the end of the filename indicates to locald that this script should be run at shutdown.
If you want to run the menu update on startup instead, rename the file to `grub-btrfs-update.start`
* Works for snapper and timeshift
##### Warning : ##### Warning :
by default, `grub-mkconfig` command is used. by default, `grub-mkconfig` command is used.
Might be `grub2-mkconfig` on some systems (Fedora ...). Might be `grub2-mkconfig` on some systems (Fedora ...).
Edit `GRUB_BTRFS_MKCONFIG` variable in `/etc/default/grub-btrfs/config` file to reflect this. Edit `GRUB_BTRFS_MKCONFIG` variable in `/etc/default/grub-btrfs/config` file to reflect this.
## - - -
### 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)
## - - -

55
config
View File

@@ -8,18 +8,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"
@@ -62,6 +54,16 @@
# Default: "" # Default: ""
#GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery" #GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"
# Booting on read-only snapshots can be tricky. (See https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
# Based on several reports, "/var" must be writable to start properly.
# Systemd can do this for you. (not compatible with OpenRC)
# The snapshot will boot in read-only mode but "/var" will be writable using a "tmpfs" mount point (which means, folder mounted in RAM)
# This should make it easier to rollback.
# Note to all: Detecting "systemd" as the default init on the snapshot is automatic, if don't, file a bug report at https://github.com/Antynea/grub-btrfs.
# Note to Arch Linux users: If you use the "grub-btrfs-overlayfs" option on Arch Linux, "GRUB_BTRFS_SYSTEMD_VOLATILE" will do nothing.
# Default: "false"
#GRUB_BTRFS_SYSTEMD_VOLATILE=true
# 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.
@@ -74,19 +76,22 @@ 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 of snapper's snapshot during run "grub-mkconfig". # Ignore specific type/tag of snapshot during run "grub-mkconfig".
# For snapper:
# Type = single, pre, post. # Type = single, pre, post.
# For Timeshift:
# Tag = boot, ondemand, hourly, daily, weekly, monthly.
# Default: ("") # Default: ("")
GRUB_BTRFS_IGNORE_SNAPPER_TYPE=("") #GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("")
# Ignore specific description of snapper's snapshot during run "grub-mkconfig". # Ignore specific description of snapshot during run "grub-mkconfig".
# e.g: timeline
# Default: ("") # Default: ("")
GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION=("") #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"
@@ -111,10 +116,16 @@ GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION=("")
# Default: grub-mkconfig # 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

6
grub-btrfs-openrc Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
echo $$ > /run/grub-btrfsd.pid
while true; do sleep 1 && inotifywait -e create -e delete /run/timeshift/backup/timeshift-btrfs/snapshots && sleep 5 && if [ -s "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub-btrfs.cfg" ]; then /etc/grub.d/41_snapshots-btrfs; else ${GRUB_BTRFS_MKCONFIG:-grub-mkconfig} -o ${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub.cfg; fi ; done

14
grub-btrfsd Executable file
View File

@@ -0,0 +1,14 @@
#!/sbin/openrc-run
# Copyright 1999-2021 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
name="grub-btrfs daemon"
command="/usr/bin/grub-btrfs-openrc"
pidfile="/run/{RC_SVCNAME}.pid"
command_background=true
depend() {
use localmount
}