Compare commits

...

7 Commits
2.2 ... 3.1

Author SHA1 Message Date
Antynea
b8325cf134 Fix: some functions doesn't work as expected (#48)
* Fix: Title format in grub-menu

function: 
- title_format , doesn't work as expected

replace print message with default parameter (p/d/n)

* Update header

- Add Github link
- Clear up some explanations

* Fix: path to grub-mkconfig_lib

. "$pkgdatadir/grub-mkconfig_lib" doesn't work on some distribution
Replaced by . "$datarootdir/grub/grub-mkconfig_lib"

* Fix: matches kernel & initramfs

matches kernel & initramfs doesn't work as expected
2018-04-19 15:45:59 +02:00
Antynea
c5da4014ae Update readme to v3.xx
Update readme to v3.xx

GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="true" 
Doesn't exist anymore

GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot")
Delete "nosnapshot" it is confusing

New option available :
GRUB_BTRFS_DISABLE="true"
(Disable grub-btrfs)
2018-04-17 12:18:56 +02:00
Antynea
8508cac7d8 GRUB shouldn't break anymore (#46)
* Update 41_snapshots-btrfs

Enhanced error handling :
	- new function available: print_error
	- if btrfs-progs is not present, print a error and exit

New options in etc/default/grub 
	- disable this script
		
Enhanced menuentries:
	- menuentries is now store in new grub configfile (/boot/grub/grub.cfg)
	- use new functions for make a menuentry: make_menu_entries and entry
	- harmonize menuentry with matching version kernel&initramfs # initramfs-linux-fallback is include and not boot with intel-ucode if exist , same as original patch in GRUB for Arch Linux
	- make a menuentry in Grub menu (grub.cfg) to load our configfile

Enhanced /boot detection:
	- create two separate function for make menuentries, if /boot is on a separate partition, use function boot_separate, else, boot_bounded
	- if no kernel found, print a message and exit
	- if no initramfs found, print a message and exit

Delete function: boot_dir
No longer uses gettext_printf function of grub-mkconfig_lib

New function to detect kernel:
	- add all original standard kernel
	- verifying if kernel exist before to continue

New functionto  detect initramfs:
	- add all original standard initramfs
	- verifying if initramfs exist before to continue
	
New function to detect microcode

New counter:
	- add a counter to show a warning if the total menuentries made exceeds 250 entries

Purge some obsolete code

Size tabulation is now 4
2018-04-16 21:43:47 +02:00
Maxim Baz
a5a96fad08 Set default value of GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES to true 2018-04-06 16:28:36 +02:00
Maxim Baz
66a06be198 Set default value of GRUB_BTRFS_LIMIT to 50 2018-04-06 16:28:36 +02:00
Maxim Baz
c44eda0913 Skip ignored snapshots during generating entries, not after 2018-04-06 16:28:36 +02:00
Maxim Baz
f0b5d194c7 Add note about GRUB_BTRFS_SNAPPER_CONFIG to README 2018-04-01 21:50:13 +02:00
2 changed files with 325 additions and 264 deletions

View File

@@ -2,79 +2,86 @@
# #
# #
######################################################################################################################################################################### #########################################################################################################################################################################
# Written by: Antynea # # Written by: Antynea #
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt # # BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt #
# # # Github: https://github.com/Antynea/grub-btrfs #
# Purpose: Include btrfs snapshots at boot options (grub-menu). # # #
# # # Purpose: Include btrfs snapshots at boot options (grub-menu). #
# What this script does: # # #
# Simple rollback using snapshots you made previously. # # What this script does: #
# - Automatically List snapshots existing on root partition (btrfs). # # Simple rollback using snapshots you made previously. #
# - Automatically Detect if "/boot" is in separate partition. # # - Automatically List snapshots existing on root partition (btrfs). #
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custon name, see below.) # # - Automatically Detect if "/boot" is in separate partition. #
# - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. # # - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. #
# - Automatically detect snapper and use snapper's snapshot description if available. # # - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. #
# # # - Automatically detect snapper and use snapper's snapshot description if available. #
# How to use it: # # #
# - Add this lines to /etc/default/grub: # # How to customize it: #
# # # - Add this lines to /etc/default/grub: #
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" # # #
# (Name appearing in the Grub menu.) # # * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" # # (Name appearing in the Grub menu.) #
# (Add a name ahead your snapshots entries in the Grub menu.) # # * GRUB_BTRFS_PREFIXENTRY="Snapshot:" #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" # # (Add a name ahead your snapshots entries in the Grub menu.) #
# (Show full path snapshot or only name in the Grub menu) # # * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" #
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" # # (Show full path snapshot or only name in the Grub menu) #
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) # # * GRUB_BTRFS_TITLE_FORMAT="p/d/n" #
# * GRUB_BTRFS_LIMIT="100" # # (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) #
# (Limit the number of snapshots populated in the GRUB menu.) # # * GRUB_BTRFS_LIMIT="50" #
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" # # (Limit the number of snapshots populated in the GRUB menu.) #
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). # # * GRUB_BTRFS_SUBVOLUME_SORT="descending" #
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) # # (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). #
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" # # If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) #
# (Show snapshots found during run "grub-mkconfig") # # * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" # # (Show snapshots found during run "grub-mkconfig") #
# (Show Total of snapshots found during run "grub-mkconfig") # # * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") # # (Show Total of snapshots found during run "grub-mkconfig") #
# (Use only if you have custom kernel name or auto-detect failed.) # # * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") #
# * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") # # (Use only if you have custom kernel name.) #
# (Use only if you have custom initramfs name or auto-detect failed.) # # * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") # # (Use only if you have custom initramfs name.) #
# (Use only if you have custom intel-ucode or auto-detect failed.) # # * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") # # (Use only if you have custom intel-ucode.) #
# (Ignore specific path during run "grub-mkconfig") # # * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker") #
# * GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" # # (Ignore specific path during run "grub-mkconfig") #
# (Create entries with matching version number instead of all possible combinations of kernel and initramfs) # # * GRUB_BTRFS_SNAPPER_CONFIG="root" #
# * GRUB_BTRFS_SNAPPER_CONFIG="root" # # (Snapper's config name to use) #
# (Snapper's config name to use) # # * GRUB_BTRFS_DISABLE="false" #
# # # Disable Grub-btrfs (default=active) #
# - Generate grub.cfg (on Arch Linux use grub-mkconfig -o /boot/grub/grub.cfg) # # #
# # # - Generate grub.cfg (on Arch Linux use grub-mkconfig -o /boot/grub/grub.cfg) #
# - grub-btrfs automatically generates snapshots entries. # # #
# - You will see it appear different entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill) # # - grub-btrfs automatically generates snapshots entries. #
# # # - You will see it appear different entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill) #
# Automatically update grub # # #
# Automatically update grub #
# If you would like grub to automatically update when Snapper timeline snapshots and cleanups occur, simply install 10-update_grub.conf in the following locations: # # If you would like grub to automatically update when Snapper timeline snapshots and cleanups occur, simply install 10-update_grub.conf in the following locations: #
# - /etc/systemd/system/snapper-timeline.service.d/ # # - /etc/systemd/system/snapper-timeline.service.d/ #
# - /etc/systemd/system/snapper-cleanup.service.d/ # # - /etc/systemd/system/snapper-cleanup.service.d/ #
# Once the configuration files are in place, systemctl daemon-reload should be run to reload the units and make the changes active. # # Once the configuration files are in place, systemctl daemon-reload should be run to reload the units and make the changes active. #
# # # #
# Special thanks for assistance and contributions: #
# - My friends #
# - All contributors on Github #
# #
######################################################################################################################################################################### #########################################################################################################################################################################
set -e set -e
#prefix="/usr" prefix="/usr"
#exec_prefix="${prefix}" exec_prefix="/usr"
datarootdir="/usr/share" datarootdir="/usr/share"
#datadir="${datarootdir}"
sysconfdir="/etc" sysconfdir="/etc"
. "${datarootdir}/grub/grub-mkconfig_lib"
. "${sysconfdir}/default/grub" . "${sysconfdir}/default/grub"
. "$datarootdir/grub/grub-mkconfig_lib"
###################################### ######################################
### Variables in /etc/default/grub ### ### Variables in /etc/default/grub ###
###################################### ######################################
## Disable Grub-btrfs (default=active)
grub_btrfs_disable=${GRUB_BTRFS_DISABLE:-"false"}
[[ "${grub_btrfs_disable}" == "true" ]] && exit 0
## Submenu name ## Submenu name
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"Arch Linux snapshots"} submenuname=${GRUB_BTRFS_SUBMENUNAME:-"Arch Linux snapshots"}
## Prefix entry ## Prefix entry
@@ -89,8 +96,8 @@ nkernel=("${GRUB_BTRFS_NKERNEL[@]}")
ninit=("${GRUB_BTRFS_NINIT[@]}") ninit=("${GRUB_BTRFS_NINIT[@]}")
## Microcode(s) name(s) ## Microcode(s) name(s)
microcode=("${GRUB_BTRFS_INTEL_UCODE[@]}") microcode=("${GRUB_BTRFS_INTEL_UCODE[@]}")
## Limit to show in the Grub menu ## Limit snapshots to show in the Grub menu
limit_snap_show="${GRUB_BTRFS_LIMIT:-100}" limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
## How to sort snapshots list ## How to sort snapshots list
snap_list_sort=${GRUB_BTRFS_SUBVOLUME_SORT:-"descending"} snap_list_sort=${GRUB_BTRFS_SUBVOLUME_SORT:-"descending"}
case "${snap_list_sort}" in case "${snap_list_sort}" in
@@ -103,12 +110,9 @@ show_snap_found=${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}
show_total_snap_found=${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"} show_total_snap_found=${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}
## Ignore specific path during run "grub-mkconfig" ## Ignore specific path during run "grub-mkconfig"
ignore_specific_path=("${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]}") ignore_specific_path=("${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]}")
## create only entries with harmonized version numbers
harmonized_entries=${GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES:-"false"}
## snapper's config name ## snapper's config name
snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"} snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
######################## ########################
### variables script ### ### variables script ###
######################## ########################
@@ -131,123 +135,99 @@ gbgmp=$(mktemp -d)
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
## boot_dir (auto-detect if /boot is separate partition or not)
boot_dir()
######################
### Error Handling ###
######################
print_error()
{ {
boot_dir="$gbgmp/$snap_dir_name/boot" local arg="$@"
[[ "$root_uuid" != "$boot_uuid" ]] && boot_dir="/boot" local nothing_to_do="If you think an error has occurred , please file a bug report at \" https://github.com/Antynea/grub-btrfs \"\n# Nothing to do. Abort.\n###### - Grub-btrfs: Snapshot detection ended - ######\n"
echo "$boot_dir" printf "# ${arg}\n# ${nothing_to_do}" >&2 ;
exit 0
} }
test_btrfs()
{
set +e
type btrfs >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
print_error "This script only supports snapshots of the btrfs filesystem, make sure you have btrfs-progs on your system."
fi
set -e
}
############## ##############
### Script ### ### Script ###
############## ##############
### BEGIN auto detect ###
## Create entry
entry() {
echo "$@" >> "/boot/grub/grub-btrfs.cfg"
# local arg="$@"
# echo "${arg}" >> "/boot/grub/grub-btrfs.cfg"
# cat << EOF >> "/boot/grub/grub-btrfs.cfg"
# ${arg}
# EOF
}
## menu entries ## menu entries
snapshots_entry() 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
echo " submenu '$title_menu' { entry "submenu '$title_menu' {
submenu '---> $title_menu <---' { echo } submenu '---> $title_menu <---' { echo }"
"
for k in "${name_kernel[@]}"; do for k in "${name_kernel[@]}"; do
[[ ! -f "${boot_dir}"/"${k}" ]] && continue;
kversion=${k#*"-"}
for i in "${name_initramfs[@]}"; do for i in "${name_initramfs[@]}"; do
prefix_i=${i%%"-"*}
suffix_i=${i#*"-"}
alt_suffix_i=${i##*"-"}
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
else continue ;
fi
for u in "${name_microcode[@]}"; do for u in "${name_microcode[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then if [[ -f "${boot_dir}"/"${u}" && "${i}" != "${prefix_i}-${kversion}-${alt_suffix_i}" ]] ; then
echo "\ 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
echo "\ 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
echo "\ entry "\
$(save_default_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 set gfxpayload=keep
set gfxpayload=keep insmod ${boot_fs}
insmod ${boot_fs} if [ x\$feature_platform_search_hint = xy ]; then
if [ x\$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root ${hs_boot} ${boot_uuid}
search --no-floppy --fs-uuid --set=root ${hs_boot} ${boot_uuid} 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_time}" "${snap_dir_name}"' echo 'Loading Kernel: "${k}" ...'
echo 'Loading Kernel: "${k}" ...' linux \"${boot_dir_root_grub}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}"
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}" if [[ -f "${boot_dir}"/"${u}" && "${i}" != "${prefix_i}-${kversion}-${alt_suffix_i}" ]] ; then
if [ -f "$(boot_dir)"/"${u}" ] ; then entry "\
echo "\ 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_real_path}/"${u}"\" \"${boot_dir_real_path}/"${i}"\"" else
else entry "\
echo "\ echo 'Loading Initramfs: "${i}" ...'
echo 'Loading Initramfs: "${i}" ...' initrd \"${boot_dir_root_grub}/"${i}"\""
initrd \"${boot_dir_real_path}/"${i}"\"" fi
fi entry " }"
echo " }" count_warning_menuentries=$((1+$count_warning_menuentries))
done done
done done
done done
echo " }" entry "}"
}
harmonized_snapshots_entry()
{
## \" required for snap,kernels,init,microcode with space in their name
echo " submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }
"
for k in "${name_kernel[@]}"; do
version=${k#vmlinuz-}
i=""
if [ -f "$(boot_dir)"/initramfs-"${version}".img ]; then
i=initramfs-${version}.img
else
if [ -f "$(boot_dir)"/initrd.img-"${version}" ]; then
i=initrd.img-${version}
fi
fi
for u in "${name_microcode[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
else
echo "\
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
fi
echo "\
$(save_default_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 ${hs_boot} ${boot_uuid}
else
search --no-floppy --fs-uuid --set=root ${boot_uuid}
fi
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
echo 'Loading Kernel: "${k}" ...'
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}"
if [ -f "$(boot_dir)"/"${i}" ] ; then
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
initrd \"${boot_dir_real_path}/"${u}"\" \"${boot_dir_real_path}/"${i}"\""
else
echo "\
echo 'Loading Initramfs: "${i}" ...'
initrd \"${boot_dir_real_path}/"${i}"\""
fi
fi
echo " }"
done
done
echo " }"
} }
## Trim a string from leading and trailing whitespaces ## Trim a string from leading and trailing whitespaces
@@ -281,10 +261,21 @@ snapshot_list()
IFS=$oldIFS IFS=$oldIFS
snap=($snap) snap=($snap)
local snap_path_name=${snap[@]:13:${#snap[@]}} local snap_path_name=${snap[@]:13:${#snap[@]}}
# Discard deleted snapshots # Discard deleted snapshots
if [ "$snap_path_name" = "DELETED" ]; then continue; fi if [ "$snap_path_name" = "DELETED" ]; then continue; fi
[[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"} [[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"}
# ignore specific path during run "grub-mkconfig"
if [ ! -z "${ignore_specific_path}" ] ; then
for isp in ${ignore_specific_path[@]} ; do
[[ "${snap_path_name}" == "${isp}"/* ]] && continue 2;
done
fi
# detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue;
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
ids+=("$id") ids+=("$id")
@@ -330,15 +321,19 @@ snapshot_list()
## Detect kernels in "/boot" ## Detect kernels in "/boot"
detect_kernel() detect_kernel()
{ {
## Arch original kernel (auto-detect) list_kernel=()
for akernel in "$(boot_dir)"/vmlinuz-* ; do # Original kernel (auto-detect)
list_kernel+=("$akernel") for okernel in "${boot_dir}"/vmlinuz-* \
"${boot_dir}"/vmlinux-* \
"${boot_dir}"/kernel-* ; do
[[ ! -f "${okernel}" ]] && continue;
list_kernel+=("$okernel")
done done
## Custom name kernel in GRUB_BTRFS_NKERNEL # Custom name kernel in GRUB_BTRFS_NKERNEL
if [ ! -z "${nkernel}" ] ; then if [ ! -z "${nkernel}" ] ; then
for ckernel in "${nkernel[@]}" ; do for ckernel in "${boot_dir}/${nkernel[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${ckernel}" ]] && continue; [[ ! -f "${ckernel}" ]] && continue;
list_kernel+=("$ckernel") list_kernel+=("$ckernel")
done done
fi fi
@@ -347,15 +342,21 @@ detect_kernel()
## Detect initramfs in "/boot" ## Detect initramfs in "/boot"
detect_initramfs() detect_initramfs()
{ {
## Arch original initramfs (auto-detect) list_initramfs=()
for ainitramfs in "$(boot_dir)"/initramfs-* ; do # Original initramfs (auto-detect)
list_initramfs+=("$ainitramfs") for oinitramfs in "${boot_dir}"/initrd.img-* \
"${boot_dir}"/initrd-*.img \
"${boot_dir}"/initrd-*.gz \
"${boot_dir}"/initramfs-*.img \
"${boot_dir}"/initramfs-*.gz ; do
[[ ! -f "${oinitramfs}" ]] && continue;
list_initramfs+=("$oinitramfs")
done done
## Custom name initramfs in GRUB_BTRFS_NINIT # Custom name initramfs in GRUB_BTRFS_NINIT
if [ ! -z "$ninit" ] ; then if [ ! -z "$ninit" ] ; then
for cinitramfs in "${ninit[@]}" ; do for cinitramfs in "${boot_dir}/${ninit[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${cinitramfs}" ]] && continue; [[ ! -f "${cinitramfs}" ]] && continue;
list_initramfs+=("$cinitramfs") list_initramfs+=("$cinitramfs")
done done
fi fi
@@ -364,18 +365,21 @@ detect_initramfs()
## Detect microcode in "/boot" ## Detect microcode in "/boot"
detect_microcode() detect_microcode()
{ {
## Arch original intel microcode list_ucode=()
for aucode in "$(boot_dir)"/intel-ucode.img ; do # Original intel microcode
list_ucode+=("$aucode") for oiucode in "${boot_dir}"/intel-ucode.img ; do
[[ ! -f "${oiucode}" ]] && continue;
list_ucode+=("$oiucode")
done done
## Custom name microcode in GRUB_BTRFS_INTEL_UCODE # Custom name microcode in GRUB_BTRFS_INTEL_UCODE
if [ ! -z "$microcode" ] ; then if [ ! -z "$microcode" ] ; then
for cucode in "${microcode[@]}" ; do for cucode in "${boot_dir}/${microcode[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${cucode}" ]] && continue [[ ! -f "${cucode}" ]] && continue
list_ucode+=("$cucode") list_ucode+=("$cucode")
done done
fi fi
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
} }
## Show full path snapshot or only name ## Show full path snapshot or only name
@@ -391,103 +395,156 @@ path_snapshot()
title_format() title_format()
{ {
case "${title_format}" in case "${title_format}" in
p/d/n) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}";;
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";; p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
p/d) title_menu="${prefixentry} ${snap_date_time}";; p/d) title_menu="${prefixentry} ${snap_date_time}";;
p/n) title_menu="${prefixentry} ${name_snapshot}";; p/n) title_menu="${prefixentry} ${name_snapshot}";;
d/n) title_menu="${snap_date_time} ${name_snapshot}";; d/n) title_menu="${snap_date_time} ${name_snapshot}";;
n/d) title_menu="${name_snapshot} ${snap_date_time}";; n/d) title_menu="${name_snapshot} ${snap_date_time}";;
p) title_menu="${prefixentry}";; p) title_menu="${prefixentry}";;
d) title_menu="${snap_date_time}";; d) title_menu="${snap_date_time}";;
n) title_menu="${name_snapshot}";; n) title_menu="${name_snapshot}";;
*) gettext_printf $"# Warning: GRUB_BTRFS_TITLE_FORMAT=${title_format}, syntax error \n" >&2 *) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}"
esac esac
} }
## List of kernels, initramfs and microcode in snapshots ## List of kernels, initramfs and microcode in snapshots
list_kernels_initramfs() boot_bounded()
{ {
# Initialize menu entries
IFS=$'\n' IFS=$'\n'
count_limit_snap=0
for item in $(snapshot_list); do for item in $(snapshot_list); do
### fix: limit_snap_show=0 # fix: limit_snap_show=0
[[ ${limit_snap_show} -le 0 ]] && break; [[ ${limit_snap_show} -le 0 ]] && break;
IFS=$oldIFS IFS=$oldIFS
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
snap_dir_name="$(echo "$item" | cut -d'|' -f2)" snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
snap_dir_name="$(trim "$snap_dir_name")" snap_dir_name="$(trim "$snap_dir_name")"
### ignore specific path during run "grub-mkconfig"
if [ ! -z "${ignore_specific_path}" ] ; then
for isp in ${ignore_specific_path[@]} ; do
[[ "${gbgmp}"/"${snap_dir_name}" == "${gbgmp}"/"${isp}"/* ]] && continue 2;
done
fi
### detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_dir_name/boot" ]] && continue;
### show snapshot found during run "grub-mkconfig"
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)" snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")" snap_date_time="$(trim "$snap_date_time")"
if [[ "${show_snap_found}" = "true" ]]; then
gettext_printf $"# Found snapshot: %s\n" "$item" >&2 ; boot_dir="$gbgmp/$snap_dir_name/boot"
fi # Kernel (Original + custom kernel)
### Kernel (auto-detect + custom kernel)
unset list_kernel
detect_kernel detect_kernel
if [ -z "${list_kernel}" ]; then continue; fi
name_kernel=("${list_kernel[@]##*"/"}") name_kernel=("${list_kernel[@]##*"/"}")
# echo "kernel = ${name_kernel[*]}" # Initramfs (Original + custom initramfs)
if [[ "${harmonized_entries}" != "true" ]]; then detect_initramfs
### Initramfs (autodetect + custom initramfs) if [ -z "${list_initramfs}" ]; then continue; fi
unset list_initramfs name_initramfs=("${list_initramfs[@]##*"/"}")
detect_initramfs # microcode (intel-ucode + custom microcode)
name_initramfs=("${list_initramfs[@]##*"/"}")
# echo "initramfs = ${name_initramfs[*]}"
fi
### microcode (auto-detect + custom microcode)
unset list_ucode
detect_microcode detect_microcode
name_microcode=("${list_ucode[@]##*"/"}") name_microcode=("${list_ucode[@]##*"/"}")
# echo "ucode = ${name_microcode[*]}" # show snapshot found during run "grub-mkconfig"
### real path to boot if [[ "${show_snap_found}" = "true" ]]; then
boot_dir_real_path="$(make_system_path_relative_to_its_root "$(boot_dir)")" printf $"# Found snapshot: %s\n" "$item" >&2 ;
### Create menu entries
## name snapshot
path_snapshot
## title menu custom
title_format
# echo "${title_menu}"
if [[ "${harmonized_entries}" = "false" ]]; then
snapshots_entry
else
harmonized_snapshots_entry
fi fi
# Show full path snapshot or only name
path_snapshot
# 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" ### 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
IFS=$oldIFS
}
boot_separate()
{
boot_dir="/boot"
# 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
if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
name_kernel=("${list_kernel[@]##*"/"}")
# Initramfs (Original + custom initramfs)
detect_initramfs
if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi
name_initramfs=("${list_initramfs[@]##*"/"}")
# microcode (auto-detect + custom microcode)
detect_microcode
name_microcode=("${list_ucode[@]##*"/"}")
# Initialize menu entries
IFS=$'\n'
for item in $(snapshot_list); do
# fix: limit_snap_show=0
[[ ${limit_snap_show} -le 0 ]] && break;
IFS=$oldIFS
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
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")"
# show snapshot found during run "grub-mkconfig"
if [[ "${show_snap_found}" = "true" ]]; then
printf $"# Found snapshot: %s\n" "$item" >&2 ;
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"
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
} }
### END auto detect ###
### Start ### ### Start ###
gettext_printf "###### - Grub-btrfs: Auto-detect Start - ######\n" >&2 ; printf "###### - Grub-btrfs: Snapshot detection started - ######\n" >&2 ;
### create mount point and mounts # if btrfs prog isn't installed, exit
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp test_btrfs
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/ # Delete existing config
### Create a menu in grub #rm -f --preserve-root "/boot/grub/grub-btrfs.cfg"
echo "submenu '${submenuname}' {" > "/boot/grub/grub-btrfs.cfg"
list_kernels_initramfs ; # Create mount point then mounting
## show total found snapshots [[ ! -d $gbgmp ]] && mkdir -p $gbgmp
if [[ "${show_total_snap_found}" = "true" ]]; then mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
gettext_printf "# Found ${count_limit_snap} snapshot(s)\n" >&2 ; # Count menuentries
fi count_warning_menuentries=0
## if no snapshot found, show a warning # Count snapshots
if [[ "${count_limit_snap}" = "0" ]]; then count_limit_snap=0
echo " submenu '---> "No snapshot found : Press ESC to return previous menu" <---' { echo } "; # Detects if /boot is a separate partition
gettext_printf "# No snapshot found \n# make sure you have at least one snapshot \n# or please file a bug report at \"https://github.com/Antynea/grub-btrfs\"\n" >&2 ; if [[ "$root_uuid" != "$boot_uuid" ]]; then
fi printf "# Info: Separate boot partition detected \n" >&2 ;
echo "}" boot_separate
## unmount mount point else
umount $gbgmp printf "# Info: Separate boot partition not detected \n" >&2 ;
gettext_printf "###### - Grub-btrfs: Auto-detect End - ######\n" >&2 ; boot_bounded
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 [[ "${show_total_snap_found}" = "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
root_grub="$(make_system_path_relative_to_its_root /boot/grub)"
# Make a submenu in GRUB (grub.cfg)
cat << EOF
submenu '${submenuname}' {
configfile "${root_grub}/grub-btrfs.cfg"
}
EOF
printf "###### - Grub-btrfs: Snapshot detection ended - ######\n" >&2 ;
### End ### ### End ###

View File

@@ -2,14 +2,14 @@
## grub-btrfs ## grub-btrfs
This is a version 2.xx of grub-btrfs This is a version 3.xx of grub-btrfs
##### BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt ##### BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
## ##
### Description ### Description
grub-btrfs, Include btrfs snapshots at boot options. (grub menu) grub-btrfs, Include btrfs snapshots at boot options. (grub menu)
## ##
### What does grub-btrfs v2.xx do : ### What does grub-btrfs v3.xx do :
Simple rollback using snapshots you made previously. Simple rollback using snapshots you made previously.
@@ -17,14 +17,15 @@ Simple rollback using snapshots you made previously.
* 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. (For custom name, see below.) * Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots.
* Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. * Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback.
* Automatically detect snapper and use snapper's snapshot description if available. * Automatically detect snapper and use snapper's snapshot description if available.
## ##
### How to use it: ### How to customize it:
You have the possibility to modify many parameters.
Add this lines to /etc/default/grub: Add this lines to /etc/default/grub:
* GRUB_BTRFS_SUBMENUNAME="Arch Linux Snapshots" * GRUB_BTRFS_SUBMENUNAME="Arch Linux Snapshots"
@@ -43,19 +44,19 @@ Add this lines to /etc/default/grub:
(Custom title, shows/hides p"prefix" d"date" n"name" in grub-menu, separator "/", custom order available) (Custom title, shows/hides p"prefix" d"date" n"name" in grub-menu, separator "/", custom order available)
* GRUB_BTRFS_NKERNEL=("vmlinuz-linux") * GRUB_BTRFS_NKERNEL=("kernel-custom")
(Use only if you have a custom kernel name or auto-detect failed.) (Use it only if you have a custom kernel name)
* GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") * GRUB_BTRFS_NINIT=("initramfs-custom.img" "initrd.img-custom")
(Use only if you have a custom initramfs name or auto-detect failed.) (Use it only if you have a custom initramfs name)
* GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img")
(Use only if you have custom intel-ucode or auto-detect failed.) (Use it only if you have custom intel-ucode)
* GRUB_BTRFS_LIMIT="100" * GRUB_BTRFS_LIMIT="50"
(Limit the number of snapshots populated in the GRUB menu.) (Limit the number of snapshots populated in the GRUB menu.)
@@ -73,14 +74,17 @@ Add this lines to /etc/default/grub:
(Show Total number of snapshots found during run "grub-mkconfig") (Show Total number of snapshots found during run "grub-mkconfig")
* GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker")
(Ignore specific path during run "grub-mkconfig") (Ignore specific path during run "grub-mkconfig")
* GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" * GRUB_BTRFS_SNAPPER_CONFIG="root"
(Create entries with matching version number instead of all possible combinations of kernel and initramfs, very useful with debian-like distributions) (Snapper's config name to use)
* GRUB_BTRFS_DISABLE="true"
(Disable grub-btrfs)
Generate grub.cfg (on Arch linux use grub-mkconfig -o /boot/grub/grub.cfg ) Generate grub.cfg (on Arch linux use grub-mkconfig -o /boot/grub/grub.cfg )