Compare commits

...

16 Commits
v1.9 ... v2.0

Author SHA1 Message Date
Maxim Baz
49c64425eb Use snapper's snapshot description if available, fixes #34 (#35)
* Use snapper's snapshot description if available, fixes #34

* List snapper's snapshot from all configs

* fix: Title format in grub-menu, that didn't work as expected
2018-01-03 21:15:26 +01:00
Antynea
cb4040cd24 fix issue #27
and add "Display name of microcode in menuentry when available"
2016-11-25 01:09:34 +01:00
Antynea
55d5a4c5c2 Merge pull request #26 from daftaupe/patch-1
Update the top-level subvolid from 0 to 5.
2016-11-18 14:40:19 +01:00
Pierre-Alain TORET
bfa42253e0 Fix typo 2016-11-18 14:23:23 +01:00
Pierre-Alain TORET
13f263ca0c Update the top-level subvolid from 0 to 5.
According to https://btrfs.wiki.kernel.org/index.php/SysadminGuide#Subvolumes, the toplevel subvolume is 5 not 0, so I guess that's what should be used here.
Also fixed a few typos.
2016-11-18 12:10:59 +01:00
Antynea
18e36190f4 Update README.md 2016-05-04 16:19:45 +02:00
Antynea
f4c02dac09 add "Create entries with matching version number instead of all possible combinations of kernel and initramfs"
* GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" 
-----> (Create entries with matching version number instead of all possible combinations of kernel and initramfs)
2016-05-04 13:46:31 +02:00
Antynea
86c8d0a0e8 Merge pull request #22 from anyc/master
Create only entries with matching version numbers and one small improvement
2016-05-03 16:26:15 +02:00
anyc
9fcdab5277 create only entries where kernel and initramfs have the same version number 2016-05-03 16:15:20 +02:00
anyc
87932d900d use safe temporary directory 2016-05-03 11:19:33 +02:00
Antynea
f0c50d1d76 Fix : GRUB_BTRFS_LIMIT (Limit the number of snapshots populated in the GRUB menu.)
Fix : When a value =< 0, script stop correctly
fix : When a value => 1, script stop when the value is reached

e.g :
 - GRUB_BTRFS_LIMIT="0"
   script doesn't detect snapshot

 - GRUB_BTRFS_LIMIT"1" or "2" "etc..."
   script will stop the snapshot detection when value is reached
2016-04-22 15:29:38 +02:00
Antynea
87a94c19c2 Merge pull request #21 from Psykar/patch-1
Readme typos and grammar
2016-04-19 02:49:01 +02:00
Louis des Landes
c8a7214e22 Readme typos and grammar 2016-04-19 10:46:09 +10:00
Antynea
befb66e801 Update README.md 2016-04-19 02:30:07 +02:00
Antynea
7213d04a42 Update README.md 2016-04-19 02:29:09 +02:00
Antynea
5ea4c86400 Enhanced
add a option to : specific path to ignore during run grub-mkconfig
e.g :
# Found Snapshot: 2016-03-31 10:26:52 var/lib/docker/btrfs/subvolumes/74040aee4fa

docker is not a real snapshot available to boot
add : GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker") to your /etc/default/grub
and this path will be skip during run grub-mkconfig

Warning : copy exactly the right path (var/lib/docker , not /var/lib/docker/), do not put the full path
2016-04-19 02:28:19 +02:00
2 changed files with 194 additions and 51 deletions

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

@@ -15,7 +15,7 @@
# How to use it: #
# - Add this lines to /etc/default/grub: #
# #
# * GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots" #
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" #
# (Name appearing in the Grub menu.) #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" #
# (Add a name ahead your snapshots entries in the Grub menu.) #
@@ -38,10 +38,12 @@
# (Use only if you have custom initramfs name or auto-detect failed.) #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") #
# (Use only if you have custom intel-ucode or auto-detect failed.) #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosapshot") #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") #
# (Ignore specific path during run "grub-mkconfig") #
# * GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" #
# (Create entries with matching version number instead of all possible combinations of kernel and initramfs) #
# #
# - Generate grub.cfg (on Archlinux 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) #
@@ -49,7 +51,7 @@
# #
# To do: #
# #
# * Display name of microcode in menuentry when available #
# * Snapper support .... #
# #
#################################################################################################################################################
@@ -68,7 +70,7 @@ sysconfdir="/etc"
### Variables in /etc/default/grub ###
######################################
## Submenu name
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"ArchLinux Snapshots"}
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"Arch Linux snapshots"}
## Prefix entry
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"}
## Show full path snapshot or only name
@@ -95,6 +97,8 @@ show_snap_found=${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}
show_total_snap_found=${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}
## Ignore specific path during run "grub-mkconfig"
ignore_specific_path=("${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]}")
## create only entries with harmonized version numbers
harmonized_entries=${GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES:-"false"}
########################
@@ -114,7 +118,7 @@ root_uuid=$(${grub_probe} "/" --target="fs_uuid" 2>/dev/null)
## Parameters passed to the kernel
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
## Mount point location
gbgmp="/tmp/gbgmp"
gbgmp=$(mktemp -d)
## Class for theme
CLASS="--class snapshots --class gnu-linux --class gnu --class os"
## save IFS
@@ -138,14 +142,20 @@ boot_dir()
snapshots_entry()
{
## \" required for snap,kernels,init,microcode with space in their name
echo " submenu '"${title_menu[*]}"' {
submenu '---> "${title_menu[*]}" <---' { echo }
echo " submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }
"
for k in "${name_kernel[@]}"; do
for i in "${name_initramfs[@]}"; do
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 "\
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
@@ -159,8 +169,7 @@ snapshots_entry()
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}\
"
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}"
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
@@ -177,9 +186,89 @@ snapshots_entry()
echo " }"
}
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() {
local var="$*"
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
}
## List of snapshots on filesystem
snapshot_list()
{
# Query info from snapper if it is installed
type snapper >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
local snapper_ids=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 2))
local snapper_types=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 1))
IFS=$'\n'
local snapper_descriptions=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 7))
fi
IFS=$'\n'
# Parse btrfs snapshots
local entries=()
local ids=()
local max_entry_length=0
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
IFS=$oldIFS
snap=($snap)
@@ -187,8 +276,47 @@ snapshot_list()
# Discard deleted snapshots
if [ "$snap_path_name" = "DELETED" ]; then continue; fi
[[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"}
echo ${snap[@]:10:2} ${snap_path_name}
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
ids+=("$id")
local entry="${snap[@]:10:2} | ${snap_path_name}"
entries+=("$entry")
# Find max length of a snapshot entry, needed for pretty formatting
local length="${#entry}"
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
done
# Find max length of a snapshot type, needed for pretty formatting
local max_type_length=0
for id in "${ids[@]}"; do
for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$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
for i in "${!entries[@]}"; do
local id="${ids[$i]}"
local entry="${entries[$i]}"
for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$id" ]]; then
local snapper_type=$(trim "${snapper_types[$j]}")
local snapper_description=$(trim "${snapper_descriptions[$j]}")
printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description"
break
fi
done
echo "$entry"
done
IFS=$oldIFS
}
## Detect kernels in "/boot"
@@ -246,8 +374,8 @@ detect_microcode()
path_snapshot()
{
case "${path_snapshot}" in
true) name_snapshot=("${snap_dir_name}");;
*) name_snapshot=("${snap_dir_name#*"/"}")
true) name_snapshot=("${snap_full_name}");;
*) name_snapshot=("${snap_full_name#*"/"}")
esac
}
@@ -255,15 +383,15 @@ path_snapshot()
title_format()
{
case "${title_format}" in
p/d/n) title_menu=("${prefixentry}" "${snap_date_time}" "${name_snapshot}");;
p/n/d) title_menu=("${prefixentry}" "${snap_dir_name}" "${snap_date_time}");;
p/d) title_menu=("${prefixentry}" "${snap_date_time}");;
p/n) title_menu=("${prefixentry}" "${snap_dir_name}");;
d/n) title_menu=("${snap_date_time}" "${snap_dir_name}");;
n/d) title_menu=("${snap_dir_name}" "${snap_date_time}");;
p) title_menu=("${prefixentry}");;
d) title_menu=("${snap_date_time}");;
n) title_menu=("${snap_dir_name}");;
p/d/n) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}";;
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
p/d) title_menu="${prefixentry} ${snap_date_time}";;
p/n) title_menu="${prefixentry} ${name_snapshot}";;
d/n) title_menu="${snap_date_time} ${name_snapshot}";;
n/d) title_menu="${name_snapshot} ${snap_date_time}";;
p) title_menu="${prefixentry}";;
d) title_menu="${snap_date_time}";;
n) title_menu="${name_snapshot}";;
*) gettext_printf $"# Warning: GRUB_BTRFS_TITLE_FORMAT=${title_format}, syntax error \n" >&2
esac
}
@@ -274,32 +402,39 @@ list_kernels_initramfs()
IFS=$'\n'
count_limit_snap=0
for item in $(snapshot_list); do
### fix: limit_snap_show=0
[[ ${limit_snap_show} -le 0 ]] && break;
IFS=$oldIFS
item=($item)
snap_dir_name=${item[@]:2:${#item[@]}}
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")"
### 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 exist
### detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_dir_name/boot" ]] && continue;
### show snapshot found during run "grub-mkconfig"
snap_date_time=${item[@]:0:2}
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")"
if [[ "${show_snap_found}" = "true" ]]; then
gettext_printf $"# Found Snapshot: %s\n" "${snap_date_time} ${snap_dir_name}" >&2 ;
gettext_printf $"# Found snapshot: %s\n" "$item" >&2 ;
fi
### Kernel (auto-detect + custom kernel)
unset list_kernel
detect_kernel
name_kernel=("${list_kernel[@]##*"/"}")
# echo "kernel = ${name_kernel[*]}"
### Initramfs (autodetect + custom initramfs)
unset list_initramfs
detect_initramfs
name_initramfs=("${list_initramfs[@]##*"/"}")
# echo "initramfs = ${name_initramfs[*]}"
if [[ "${harmonized_entries}" != "true" ]]; then
### Initramfs (autodetect + custom initramfs)
unset list_initramfs
detect_initramfs
name_initramfs=("${list_initramfs[@]##*"/"}")
# echo "initramfs = ${name_initramfs[*]}"
fi
### microcode (auto-detect + custom microcode)
unset list_ucode
detect_microcode
@@ -308,17 +443,19 @@ list_kernels_initramfs()
### real path to boot
boot_dir_real_path="$(make_system_path_relative_to_its_root "$(boot_dir)")"
### Create menu entries
## name snpashot
## name snapshot
path_snapshot
## title menu custom
title_format
# echo "${title_menu[*]}"
snapshots_entry
### Limit snapshots found during run "grub-mkconfig"
count_limit_snap=$((1+$count_limit_snap))
if [[ $count_limit_snap -gt $limit_snap_show ]]; then
break;
fi
# echo "${title_menu}"
if [[ "${harmonized_entries}" = "false" ]]; then
snapshots_entry
else
harmonized_snapshots_entry
fi
### Limit snapshots found during run "grub-mkconfig"
count_limit_snap=$((1+$count_limit_snap))
[[ $count_limit_snap -ge $limit_snap_show ]] && break;
done
IFS=$oldIFS
}
@@ -328,13 +465,13 @@ list_kernels_initramfs()
gettext_printf "###### - Grub-btrfs: Auto-detect Start - ######\n" >&2 ;
### create mount point and mounts
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp
mount -o subvolid=0 /dev/disk/by-uuid/$root_uuid $gbgmp/
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
### Create a menu in grub
echo "submenu '${submenuname}' {"
list_kernels_initramfs ;
## show total found snapshots
if [[ "${show_total_snap_found}" = "true" ]]; then
gettext_printf "# found ${count_limit_snap} snapshot(s)\n" >&2 ;
gettext_printf "# Found ${count_limit_snap} snapshot(s)\n" >&2 ;
fi
## if no snapshot found, show a warning
if [[ "${count_limit_snap}" = "0" ]]; then
@@ -345,4 +482,4 @@ list_kernels_initramfs()
## unmount mount point
umount $gbgmp
gettext_printf "###### - Grub-btrfs: Auto-detect End - ######\n" >&2 ;
### End ###
### End ###

View File

@@ -2,7 +2,6 @@
### grub-btrfs
This is a version 1.xx of grub-btrfs
#### Description
@@ -17,7 +16,7 @@ Simple rollback using snapshots you made previously.
* 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.)
* Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custom name, see below.)
* Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback.
@@ -44,11 +43,11 @@ Add this lines to /etc/default/grub:
* GRUB_BTRFS_NKERNEL=("vmlinuz-linux")
(Use only if you have custom kernel name or auto-detect failed.)
(Use only if you have a custom kernel name or auto-detect failed.)
* GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img")
(Use only if you have custom initramfs name or auto-detect failed.)
(Use only if you have a custom initramfs name or auto-detect failed.)
* GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img")
@@ -70,7 +69,15 @@ Add this lines to /etc/default/grub:
* GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true"
(Show Total 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")
(Ignore specific path during run "grub-mkconfig")
* GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false"
(Create entries with matching version number instead of all possible combinations of kernel and initramfs)
@@ -83,8 +90,7 @@ You will see it appear differents entries (e.g : Snapshot: [2014-02-12 11:24:37]
#### TO DO
* Display name of microcode in menuentry when available
* ignore specific path
* Snapper support
## discussion