Compare commits

..

15 Commits
v1.11 ... 2.2

Author SHA1 Message Date
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
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
3 changed files with 187 additions and 93 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,59 +1,65 @@
#! /usr/bin/env bash
#
#
#################################################################################################################################################
# Written by: Antynea #
# #
# Purpose: Include btrfs snapshots at boot options (grub-menu). #
# #
# What this script does: #
# - Automatically List snapshots existing on root partition (btrfs). #
# - 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 Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. #
# #
# How to use it: #
# - Add this lines to /etc/default/grub: #
# #
# * GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots" #
# (Name appearing in the Grub menu.) #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" #
# (Add a name ahead your snapshots entries in the Grub menu.) #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" #
# (Show full path snapshot or only name in the Grub menu) #
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" #
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) #
# * GRUB_BTRFS_LIMIT="100" #
# (Limit the number of snapshots populated in the GRUB menu.) #
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" #
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). #
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) #
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" #
# (Show snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" #
# (Show Total of snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") #
# (Use only if you have 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.) #
# * 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" "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) #
# #
# - 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) #
# #
# #
# To do: #
# #
# * Snapper support .... #
# #
#################################################################################################################################################
#########################################################################################################################################################################
# Written by: Antynea #
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt #
# #
# Purpose: Include btrfs snapshots at boot options (grub-menu). #
# #
# What this script does: #
# Simple rollback using snapshots you made previously. #
# - Automatically List snapshots existing on root partition (btrfs). #
# - 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 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: #
# #
# * 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.) #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" #
# (Show full path snapshot or only name in the Grub menu) #
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" #
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) #
# * GRUB_BTRFS_LIMIT="100" #
# (Limit the number of snapshots populated in the GRUB menu.) #
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" #
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). #
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) #
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" #
# (Show snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" #
# (Show Total of snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") #
# (Use only if you have 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.) #
# * 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" "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) #
# * 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) #
# #
# - 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 #
# 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. #
# #
#########################################################################################################################################################################
set -e
@@ -70,7 +76,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
@@ -99,6 +105,8 @@ show_total_snap_found=${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}
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_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
########################
@@ -142,8 +150,8 @@ 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
@@ -189,8 +197,8 @@ snapshots_entry()
harmonized_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
version=${k#vmlinuz-}
@@ -242,9 +250,33 @@ harmonized_snapshots_entry()
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 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 2))
local snapper_types=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 1))
IFS=$'\n'
local snapper_descriptions=($(snapper -t 0 -c "$snapper_config" list | 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)
@@ -252,8 +284,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" == "$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" == "$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"
@@ -311,8 +382,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
}
@@ -320,15 +391,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
}
@@ -342,8 +413,10 @@ list_kernels_initramfs()
### 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
@@ -353,9 +426,10 @@ list_kernels_initramfs()
### 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
@@ -381,7 +455,7 @@ list_kernels_initramfs()
path_snapshot
## title menu custom
title_format
# echo "${title_menu[*]}"
# echo "${title_menu}"
if [[ "${harmonized_entries}" = "false" ]]; then
snapshots_entry
else
@@ -405,7 +479,7 @@ list_kernels_initramfs()
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

View File

@@ -1,14 +1,15 @@
[![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
#### Description
This is a version 2.xx of grub-btrfs
##### BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
##
### Description
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.
@@ -20,12 +21,13 @@ Simple rollback using snapshots you made previously.
* Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback.
#### How to use it:
* Automatically detect snapper and use snapper's snapshot description if available.
##
### How to use it:
Add this lines to /etc/default/grub:
* GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots"
* GRUB_BTRFS_SUBMENUNAME="Arch Linux Snapshots"
(Name menu appearing in grub.)
@@ -35,7 +37,7 @@ Add this lines to /etc/default/grub:
* 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"
@@ -77,21 +79,37 @@ Add this lines to /etc/default/grub:
* GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false"
(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)
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 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
##
### 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)
##