Compare commits

..

19 Commits
v2.0 ... 3.0

Author SHA1 Message Date
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
Maxim Baz
773a8bfb76 Support selecting snapper's config, default to 'root' (#41) 2018-04-01 21:38:22 +02:00
Antynea
1b40cfee20 Update 41_snapshots-btrfs
Update 41_snapshots-btrfs
2018-02-03 22:59:03 +01:00
Antynea
358dedc392 Update 41_snapshots-btrfs
Update 41_snapshots-btrfs
2018-02-03 22:57:04 +01:00
Antynea
55dc182b34 Update README.md 2018-02-03 22:31:43 +01:00
Nathan Parsons
23ddb063cb Add systemd service configuration for grub updating (#38)
* Add systemd service configuration for grub updating

This configuration file causes `update-grub` to be run after
Snapper's cleanup and timeline services are run by systemd

* Make invoked command more universal

* Note the need to run systemctl daemon-reload
2018-02-03 21:50:40 +01:00
Antynea
ca51d74265 Update README.md 2018-01-26 11:00:55 +01:00
Antynea
f8937a3fc7 Update README.md 2018-01-26 10:58:04 +01:00
Antynea
9265eb96de Update README.md 2018-01-26 10:55:45 +01:00
Antynea
72edee3d1c Update README.md 2018-01-26 10:54:37 +01:00
Antynea
d24ba197a8 Update README.md 2018-01-26 10:53:42 +01:00
Antynea
0e826391f1 Update 41_snapshots-btrfs 2018-01-26 09:19:33 +01:00
Antynea
7166d939fa Update README.md 2018-01-26 09:18:13 +01:00
Antynea
5cfbf46c8c fix Snapper id too long #36
* fix Snapper id too long #36
2018-01-07 00:31:16 +01:00
Antynea
12cb591307 Update README.md 2018-01-04 10:06:41 +01:00
3 changed files with 357 additions and 269 deletions

2
10-update_grub.conf Normal file
View File

@@ -0,0 +1,2 @@
[Service]
ExecStartPost=/usr/sbin/grub-mkconfig -o /boot/grub/grub.cfg

View File

@@ -1,74 +1,87 @@
#! /usr/bin/env bash #! /usr/bin/env bash
# #
# #
################################################################################################################################################# #########################################################################################################################################################################
# Written by: Antynea # # Written by: Antynea #
# # # BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt #
# Purpose: Include btrfs snapshots at boot options (grub-menu). # # #
# # # Purpose: Include btrfs snapshots at boot options (grub-menu). #
# What this script does: # # #
# - Automatically List snapshots existing on root partition (btrfs). # # What this script does: #
# - Automatically Detect if "/boot" is in separate partition. # # Simple rollback using snapshots you made previously. #
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custon name, see below.) # # - Automatically List snapshots existing on root partition (btrfs). #
# - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. # # - Automatically Detect if "/boot" is in separate partition. #
# # # - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custon name, see below.) #
# How to use it: # # - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. #
# - Add this lines to /etc/default/grub: # # - Automatically detect snapper and use snapper's snapshot description if available. #
# # # #
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" # # How to use it: #
# (Name appearing in the Grub menu.) # # - Add this lines to /etc/default/grub: #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" # # #
# (Add a name ahead your snapshots entries in the Grub menu.) # # * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" # # (Name appearing in the Grub menu.) #
# (Show full path snapshot or only name in the Grub menu) # # * GRUB_BTRFS_PREFIXENTRY="Snapshot:" #
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" # # (Add a name ahead your snapshots entries in the Grub menu.) #
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) # # * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" #
# * GRUB_BTRFS_LIMIT="100" # # (Show full path snapshot or only name in the Grub menu) #
# (Limit the number of snapshots populated in the GRUB menu.) # # * GRUB_BTRFS_TITLE_FORMAT="p/d/n" #
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" # # (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) #
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). # # * GRUB_BTRFS_LIMIT="50" #
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) # # (Limit the number of snapshots populated in the GRUB menu.) #
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" # # * GRUB_BTRFS_SUBVOLUME_SORT="descending" #
# (Show snapshots found during run "grub-mkconfig") # # (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" # # If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) #
# (Show Total of snapshots found during run "grub-mkconfig") # # * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") # # (Show snapshots found during run "grub-mkconfig") #
# (Use only if you have custom kernel name or auto-detect failed.) # # * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" #
# * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") # # (Show Total of snapshots found during run "grub-mkconfig") #
# (Use only if you have custom initramfs name or auto-detect failed.) # # * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") # # (Use only if you have custom kernel name or auto-detect failed.) #
# (Use only if you have custom intel-ucode or auto-detect failed.) # # * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") # # (Use only if you have custom initramfs name or auto-detect failed.) #
# (Ignore specific path during run "grub-mkconfig") # # * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") #
# * GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" # # (Use only if you have custom intel-ucode or auto-detect failed.) #
# (Create entries with matching version number instead of all possible combinations of kernel and initramfs) # # * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") #
# # # (Ignore specific path during run "grub-mkconfig") #
# - Generate grub.cfg (on Arch Linux use grub-mkconfig -o /boot/grub/grub.cfg) # # * GRUB_BTRFS_SNAPPER_CONFIG="root" #
# # # (Snapper's config name to use) #
# - grub-btrfs automatically generates snapshots entries. # # * GRUB_BTRFS_DISABLE="false" #
# - You will see it appear different entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill) # # Disable Grub-btrfs (default=active) #
# # # #
# # # - Generate grub.cfg (on Arch Linux use grub-mkconfig -o /boot/grub/grub.cfg) #
# To do: # # #
# # # - grub-btrfs automatically generates snapshots entries. #
# * Snapper support .... # # - You will see it appear different entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill) #
# # # #
################################################################################################################################################# # 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: #
# - /etc/systemd/system/snapper-timeline.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. #
# #
# 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"
. "$pkgdatadir/grub-mkconfig_lib"
# . "$datarootdir/grub/grub-mkconfig_lib" # Uncomment if you run "bash -x"
###################################### ######################################
### 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
@@ -83,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
@@ -97,9 +110,8 @@ 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 ## snapper's config name
harmonized_entries=${GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES:-"false"} snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
######################## ########################
### variables script ### ### variables script ###
@@ -123,123 +135,98 @@ 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[@]##*"-"}
if [ -f "${boot_dir}"/"${prefix_i}-${kversion}-${suffix_i}" ]; then i="${i}";
elif [ -f "${boot_dir}"/"${prefix_i}-${kversion}" ]; then i="${i}";
elif [ -f "${boot_dir}"/"${prefix_i}-${kversion}.img" ]; then i="${i}";
elif [ -f "${boot_dir}"/"${prefix_i}-${kversion}.gz" ]; 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}" != initramfs-linux-fallback.img ]] ; 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}" != initramfs-linux-fallback.img ]] ; 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
@@ -256,11 +243,11 @@ snapshot_list()
# Query info from snapper if it is installed # Query info from snapper if it is installed
type snapper >/dev/null 2>&1 type snapper >/dev/null 2>&1
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
local snapper_ids=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 2)) local snapper_ids=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 2))
local snapper_types=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 1)) local snapper_types=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 1))
IFS=$'\n' IFS=$'\n'
local snapper_descriptions=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 7)) local snapper_descriptions=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 7))
fi fi
IFS=$'\n' IFS=$'\n'
@@ -273,10 +260,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")
@@ -293,7 +291,7 @@ snapshot_list()
for id in "${ids[@]}"; do for id in "${ids[@]}"; do
for j in "${!snapper_ids[@]}"; do for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}" local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$id" ]]; then if [[ "$snapper_id" == "$id" ]]; then
local snapper_type=$(trim "${snapper_types[$j]}") local snapper_type=$(trim "${snapper_types[$j]}")
local length="${#snapper_type}" local length="${#snapper_type}"
[[ "$length" -gt "$max_type_length" ]] && max_type_length=$length [[ "$length" -gt "$max_type_length" ]] && max_type_length=$length
@@ -306,7 +304,7 @@ snapshot_list()
local entry="${entries[$i]}" local entry="${entries[$i]}"
for j in "${!snapper_ids[@]}"; do for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}" local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$id" ]]; then if [[ "$snapper_id" == "$id" ]]; then
local snapper_type=$(trim "${snapper_types[$j]}") local snapper_type=$(trim "${snapper_types[$j]}")
local snapper_description=$(trim "${snapper_descriptions[$j]}") local snapper_description=$(trim "${snapper_descriptions[$j]}")
printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description" printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description"
@@ -322,15 +320,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
@@ -339,15 +341,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
@@ -356,18 +364,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
@@ -392,94 +403,148 @@ title_format()
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 *) printf $"# Warning: GRUB_BTRFS_TITLE_FORMAT=${title_format}, syntax error \n" >&2
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

@@ -1,14 +1,15 @@
[![GitHub release](https://img.shields.io/github/release/Antynea/grub-btrfs.svg)](https://github.com/Antynea/grub-btrfs) [![GitHub release](https://img.shields.io/github/release/Antynea/grub-btrfs.svg)](https://github.com/Antynea/grub-btrfs)
### grub-btrfs ## grub-btrfs
This is a version 1.xx of grub-btrfs This is a version 2.xx of grub-btrfs
##### 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 v1.xx do : ### What does grub-btrfs v2.xx do :
Simple rollback using snapshots you made previously. Simple rollback using snapshots you made previously.
@@ -20,12 +21,13 @@ Simple rollback using snapshots you made previously.
* 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.
#### How to use it: ##
### How to use it:
Add this lines to /etc/default/grub: Add this lines to /etc/default/grub:
* GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots" * GRUB_BTRFS_SUBMENUNAME="Arch Linux Snapshots"
(Name menu appearing in grub.) (Name menu appearing in grub.)
@@ -35,7 +37,7 @@ Add this lines to /etc/default/grub:
* GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true"
(Show full path snapshot or only name) (Show full path snapshot or only name, weird reaction with snapper)
* GRUB_BTRFS_TITLE_FORMAT="p/d/n" * GRUB_BTRFS_TITLE_FORMAT="p/d/n"
@@ -53,7 +55,7 @@ Add this lines to /etc/default/grub:
(Use only if you have custom intel-ucode or auto-detect failed.) (Use only if you have custom intel-ucode or auto-detect failed.)
* 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.)
@@ -75,23 +77,42 @@ Add this lines to /etc/default/grub:
(Ignore specific path during run "grub-mkconfig") (Ignore specific path during run "grub-mkconfig")
* GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" * GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="true"
(Create entries with matching version number instead of all possible combinations of kernel and initramfs) (Create entries with matching version number instead of all possible combinations of kernel and initramfs, very useful with debian-like distributions)
* GRUB_BTRFS_SNAPPER_CONFIG="root"
(Snapper's config name to use)
Generate grub.cfg (on Arch linux use grub-mkconfig -o /boot/grub/grub.cfg )
Generate grub.cfg (on Archlinux use grub-mkconfig -o /boot/grub/grub.cfg )
grub-btrfs automatically generates snapshots entries. grub-btrfs automatically generates snapshots entries.
You will see it appear differents entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill ) You will see it appear differents entries (e.g : Snapshot: 2018-01-03 15:08:41 @test1 )
##
### 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:
#### TO DO - `/etc/systemd/system/snapper-timeline.service.d/`
- `/etc/systemd/system/snapper-cleanup.service.d/`
* Snapper support Once the configuration files are in place, `systemctl daemon-reload` should be run to reload the units and make the changes active.
##
## discussion ### Discussion
Pour les francophones : https://forums.archlinux.fr/viewtopic.php?f=18&t=17177 Pour les francophones : https://forums.archlinux.fr/viewtopic.php?f=18&t=17177
##
### Special thanks for assistance and contributions
* [maximbaz](https://github.com/maximbaz)
* [crossroads1112](https://github.com/crossroads1112)
* [penetal](https://github.com/penetal)
* [wesbarnett](https://github.com/wesbarnett)
* [Psykar](https://github.com/Psykar)
* [anyc](https://github.com/anyc)
* [daftaupe](https://github.com/daftaupe)
* [N-Parsons](https://github.com/N-Parsons)
##