Compare commits

...

61 Commits
3.1 ... v4.8

Author SHA1 Message Date
Kriss
d68fdf5fff Adds a new config variable "GRUB_BTRFS_ROOTFLAGS" (#133)
Script:

Improves the rootflags option in the kernel command line:
- Remove "rw" flag.
- Parse fstab mountoptions and add them to rootflags:
Adds functionality to read in  snapshot specific mount flags
from the respective fstab and uses them in combination with the new 
config option, while the latter is prioritized.
Both places can, but don't need to define mount flags. If either of them
doesn't, it will simply not be taken into account.

Config file:

Adds a new config variable "GRUB_BTRFS_ROOTFLAGS":
- The new variable is used to include user-defined rootflags in the 
kernel command line of generated snapshot bootmenu entries.
See config file for more infos.
2021-01-11 13:37:40 +01:00
Kriss
87168d2d50 [Makefile] Modifies install/uninstall target. Adds help target (#135)
Makefile:

Install target:
- Added "uninstall" and "help" target to ".phony".
- Hook initcpio will be installed only on Arch Linux like distributions.

Uninstall target:
- All commands are in silent mode.
- "rmdir" command will not interrupt the uninstallation if the folder does not exist.
- Remove "-r" option to "rm" command.
- Fix a mistake in deleting the "readme" file.
- Uninstalling the "grub-btrfs.cfg" file uses the "GRUB_BTRFS_GRUB_DIRNAME" variable.
- Delete initcpio folder if not on Arch.
- Delete "grub-btrfs" docs and licenses folders.

help target:
- Add "help" target.
2021-01-11 13:04:09 +01:00
Antynea
a437b80a35 improves systemd service (#131)
grub-btrfs.service: remove unnecessary path for bash and grub-mkconfig command

readme.md: add warning section to systemd service section

config file: Improves the description of the variable GRUB_BTRFS_MKCONFIG
2021-01-03 14:50:34 +01:00
Antynea
9408231ecc Corrects an erroneous variable (#128)
Fix #127
Replaces "GRUB_BTRFS_DIRNAME" variable to match with new variable "GRUB_BTRFS_GRUB_DIRNAME" in config file.
2020-12-30 15:31:28 +01:00
Antynea
9722f6732c Corrects a mistake
Corrects the duplicate that appeared
Line16 should be :
`@install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-hook" "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"		# Arch Linux only`
2020-10-22 21:19:54 +02:00
Antynea
0ed5adaf32 Fix indentation
My IDE was set up incorrectly.
Convert all tab indentation to space.
2020-10-22 07:07:30 +02:00
Antynea
d4b97415b0 Fix #116 (#118)
* Fix #116 (#118)
  * Renames variable GRUB_BTRFS_DIRNAME to GRUB_BTRFS_GRUB_DIRNAME and improves its description

  * Adds variable GRUB_BTRFS_BOOT_DIRNAME, used to detect the boot partition and the location of kernels/initrafms/microcodes
2020-10-21 19:14:05 +02:00
Antynea
da36aa8847 Update header
* Update header about read-only snapshots.
2020-10-15 16:27:32 +02:00
Antynea
d8df766554 Update README.md
* Update link to /initramfs/readme
2020-10-14 15:29:50 +02:00
Antynea
9adce629f7 Boot on read-only snapshot (#115)
* Create a initramfs folder & configuration files
  * create a initramfs folder
  * create Arch Linux folder
  * Add `HOOK/INSTALL` files to generate a custom initrafms for boot on read-only snapshot for Arch Linux.
  * Add readme file to initramfs folder

* Makefile changes
  * Add readme file
  * Add readme file of initramfs-overlayfs
  * Add HOOK/INSTALL files for Arch Linux

* Readme changes
  * Updates the documentation to be able to boot on a read-only snapshot.
  * Redesign readme again.
2020-10-14 15:17:07 +02:00
Antynea
3c5e741641 Modify "grub btrfs dirname" variable. (#113)
* Modify "GRUB_BTRFS_DIRNAME"
  * Full path to Grub folder is now configurable (/boot is no longer hard coded).
  * Detection of the boot partition is now based on the location of the Grub folder.
  * Warning [see](https://github.com/Antynea/grub-btrfs/pull/113#issuecomment-705916729)
2020-10-09 15:50:02 +02:00
Antynea
fa65c3d6d9 move rmdir to end of uninstall section
If rmdir fails, other commands are not executed, so
move rmdir to end of uninstall section
2020-10-09 02:32:25 +02:00
Antynea
4493bdc6e4 Clean code
Remove commented commands that are no longer needed.
2020-10-07 02:00:23 +02:00
Antynea
a7289b182a Remove several variables not necessary
For easier maintenance,
remove several variables already present in the config file.
2020-10-07 00:36:06 +02:00
Antynea
0fe512776a Modify the function which is used to ignore a path. (#112)
Modify the function which is used to ignore a path.
@ shouldn't be hardcoded.
Create 2 separate functions to ignore a specific path or prefix path.
In specific path, only exact paths are ignored.
In prefix path, any path starting with the specified string will be ignored.
e.g :
if specific path = @, only @ snapshot will be ignored.
if prefix path = @, all snapshots beginning with "@/..." will be ignored.
2020-10-06 23:19:41 +02:00
Antynea
6af193c47a Add new path to ignore docker subvolume
Many distributions now use "@" as the default subvolume.
Add the following path "@/var/lib/docker" to ignore the docker subvolume.
Fix: #110
2020-10-03 12:51:51 +02:00
Antynea
9a771d9842 Stop script if root partition isn't btrfs filesystem
Add filesystem check on the root partition.
If the filesystem isn't btrfs, stop execution.
Update error message for btrfs-prog.
2020-10-01 19:37:43 +02:00
Antynea
64c08a0807 Update header
Update header to reflect change on [Automatically update grub](https://github.com/Antynea/grub-btrfs#automatically-update-grub) section
Remove many `#` characters
2020-10-01 19:28:45 +02:00
Antynea
c9b605153b Redesign readme (#109)
* Add more information

Add more information.
Due to the redesign of the "Customization" section of the readme file.

* Redesign  customization section

Move information of customization section to config file
2020-09-29 13:39:20 +02:00
Antynea
7e922abefb Update "Automatically update grub" section
Update "Automatically update grub" section.
Correct a mistake.
2020-09-28 00:58:21 +02:00
Antynea
d20439554e Update "Automatically update grub" section
Update "Automatically update grub" section.
Trying to make it more understandable.
2020-09-28 00:54:45 +02:00
Antynea
ce8261395f Update Automatically update grub section
Timeshift use `/run/timeshift/backup/timeshift-btrfs/snapshots` mountpoint for its snapshots.
Timeshift users must modify the monitoring path:
```
[Path]
PathModified=/.snapshots
```
to
```
[Path]
PathModified=/run/timeshift/backup/timeshift-btrfs/snapshots
```
2020-09-24 02:21:37 +02:00
Antynea
133c8ebfdb Clean code
Clean indentation/leading/trailing space
2020-09-16 21:07:42 +02:00
Antynea
2349282df5 Improved sorting of the subvolumes list (#107)
* Improved sorting of the subvolumes list

Add functionality to sort subvolume list by: rootid,gen,ogen,path
Default: "-rootid" means list snapshot by new ones first
See [Sorting section](https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-subvolume#SUBCOMMAND)
2020-09-16 19:16:18 +02:00
Antynea
041a9c6606 Microcode variable updated (#106)
* Microcode variable updated

* Modifying variable to reflect improved microcode detection

* Update config

Change "GRUB_BTRFS_INTEL_UCODE" to new variable "GRUB_BTRFS_CUSTOM_MICROCODE"

* Update README.md

Change "GRUB_BTRFS_INTEL_UCODE" to new variable "GRUB_BTRFS_CUSTOM_MICROCODE"
2020-09-16 18:25:11 +02:00
Antynea
7e5bfa597f Update header
* Update header
Improve the warning section about "ro snapshots"
2020-09-16 17:05:17 +02:00
Antynea
f0382536fb Update README.md
automatic microcode detection: now detects amd microcode
2020-09-16 16:21:54 +02:00
Antynea
b50ad439d4 clean code
* root_grub="$(make_system_path_relative_to_its_root /boot/$grub_directory)"
no longer used
2020-09-16 16:17:06 +02:00
Antynea
5f40f30985 Remove Internationalization
Internationalization has never been used. (default : english)
2020-09-16 14:02:02 +02:00
Antynea
d2c15acd72 Enhance microcode detection (#105)
Add all default stock images listed by "grub"
See  [GRUB_EARLY_INITRD_LINUX_STOCK](https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html) for more informations.
2020-09-16 13:54:21 +02:00
Christian Kotte
77d69aaa81 Update script output (#104)
Script output is now the same as other grub-mkconfig output
2020-09-13 09:39:38 +02:00
Antynea
44ee10f5ef Attempt to fix ignore specific path (#102)
* Attempt to fix ignore specific path

Attempt to fix ignore specific path #100

* Update config
2020-09-05 12:24:46 +02:00
Senya
9cb57dab40 Add uninstall to the Makefile (#99) 2020-08-31 12:49:59 +02:00
Antynea
6bfdf07bbf Add password protection support for the submenu (#97)
* Add password protection support for the submenu

Grub2 supports superuser and user access using passwords. #95

-Ability to add authorized users.
-Possibility to disable password protection for the submenu.

* Update config

* Update README.md
2020-08-29 18:55:39 +02:00
Antynea
7f76eec16d Update Name appearing in the Grub menu
Name appearing in the Grub menu :
Use distribution information from /etc/os-release by default
2020-08-28 04:22:13 +02:00
Antynea
a89834248c Update README.md 2020-08-28 04:19:44 +02:00
Maxim Baz
b49e19ce30 Document how to boot on read-only snapshots, fix #92 2020-08-04 19:03:35 +02:00
Maxim Baz
9b863f027b Ignore @ by default as it is never a snapshot, fix #96, fix #90 2020-07-28 19:27:47 +02:00
darkdragon-001
44771d9756 Use distribution information from /etc/os-release by default. (#94)
Fixes #87
2020-07-18 14:06:58 +02:00
Maxim Baz
18c6eebf31 Allow ignoring precise paths or names, fixes #90 2020-07-17 23:19:26 +02:00
Peter Gantner
6ff1fc7127 grub script: improve snapshot listing performance (#93)
Btrfs filesystems may be slow when listing snapshots and calculating
space usage for each.
And that space information is not needed and never used in the scipt.

So, add --disable-ununsed-space to all calls to btrfs.

See: https://github.com/Antynea/grub-btrfs/issues/91

Co-authored-by: Peter G <nephros@pearl.crownest.nephros.org>
2020-07-17 22:43:27 +02:00
Thomas Winant
92eef3079d Don't let the kernel parameters override the subvol for the snapshot (#85)
Previously, the kernel parameters came after the `rootflags=subvol=<snapshot>`
argument. This means that when the user's standard kernel parameters also
contain a `rootflags=subvol=<root>`, it will override the subvol flag of the
snapshot. So put the snapshot's subvol flag last.
2020-03-22 16:33:12 +01:00
Maxim Baz
4e1b628465 Test if snapper is properly configured before using it (#83) 2020-01-17 21:53:24 +01:00
Luflosi
21df698e04 Fix typos (#80) 2019-12-29 14:23:16 +01:00
Antynea
27335ffbaf Fixed incorrect path to the grub-btrfs.cfg file in Grub menu (#79)
Fix #72
The submenu generated by "grub-btrfs" doesn't load in the "GRUB menu."
Sometimes the Grub prefix and root variable don't match.
This ensures that the prefix variable is used to load the grub-btrfs.cfg file.
See
How to specify files
and
Special environment variables : root
and
Special environment variables : prefix
2019-12-09 22:40:33 +01:00
Antynea
6cd13037ce Fix #74 (#77)
Improving the readme and config files.
2019-12-08 18:02:05 +01:00
Hrotkó Gábor
4a882e77dc remove non numeric characters from snapshot id (#76)
Snapper support enhanced
2019-12-07 14:14:11 +01:00
Hrotkó Gábor
cb0b55a6bb add --no-dbus option to snapper list (#75)
In a chroot-ed environment, it is necessary to run snapper without dbus.
2019-12-07 12:50:57 +01:00
Antynea
2c03d5f9e2 fix #69 (#70)
Add a search command line to `grub.cfg` for find `grub-btrfs.cfg`
`search -f --set=root --no-floppy /grub/grub-btrfs.cfg`
2019-09-12 13:45:08 +02:00
Hrotkó Gábor
e286bf1a0d fix get description when quota enabled (#68) 2019-08-13 12:43:02 +02:00
Antynea
091ffc0ae9 Update EnvironmentFile (#65)
* Change `EnvironmentFile` to match the new design of the configuration file. (#64)
2018-12-15 03:35:40 +01:00
Maxim Baz
28990c45bb Update Arch Linux install instructions (#63)
added grub-btrfs to the official Arch Linux repos
2018-12-13 20:33:05 +01:00
Antynea
4c57fcbbf4 v4 (#62)
* Readme updated
* localization no longer supported
* New systemd service.
* 41_snapshots-btrfs, ahead updated
* Makefile added
2018-12-13 16:39:16 +01:00
Maxim Baz
e1532c0515 Add Makefile (#60) 2018-12-07 22:09:34 +01:00
Antynea
73a2bd3d32 Enhanced btrfs raid 0 detection (#59)
Fix #58 
- grub-probe should work properly with btrfs raid 0
2018-11-22 08:39:08 +01:00
Maxim Baz
3eb7eb7861 Support snapper 0.7.0 (#57)
Snapper changed the order of columns, ID now comes before type.
2018-10-24 00:29:06 +02:00
Nathan Parsons
35703e71c1 Make 'grub-mkconfig' command name configurable (#56)
* Make 'grub-mkconfig' command name configurable

- Use 'grub-mkconfig' as the default
- Note that some systems use 'grub2-mkconfig'
- Update 10-update_grub.conf to use the configurable grub directory name
- Refactor the systemd commands for clarity and to avoid duplicate regeneration on first run

* Update check_uuid_required() to work for partial regeneration of the GRUB menu
2018-08-15 14:02:13 +02:00
Antynea
a1a48d26b7 Override boot partition detection (#55)
* Override boot partition detection

refer to #54

* Add new option

# GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="false"  
# Change to "true" if you have a boot partition in a different subvolume

* Corrects indentation

* Update readme
GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="false"
(Change to "true" if you have a boot partition in a different subvolume)
2018-07-09 18:55:09 +02:00
Crafter6432
13a7186aaf Add systemd.path as option to monitor for new Snapshots (#53)
* Use systemd.path to regenerate grub-btrfs.cfg

* Added option GRUB_BTRFS_DIRNAME

* Updated README
2018-06-30 14:46:30 +02:00
Antynea
9b73e0ac62 Check uuid requirement. (#52)
* detect uuid requirement

add new function to detect uuid requirement

* Reduce generation time

New function doesn't need to be called at each generation of a menu entry
2018-06-11 15:52:00 +02:00
Maxim Baz
b17e7bd6a1 Add a dedicated config file (#49) 2018-04-20 18:08:37 +02:00
11 changed files with 753 additions and 513 deletions

View File

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

View File

@@ -1,70 +1,43 @@
#! /usr/bin/env bash #! /usr/bin/env bash
# #
# #
######################################################################################################################################################################### # Written by: Antynea
# Written by: Antynea # # BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt # # Github: https://github.com/Antynea/grub-btrfs
# Github: https://github.com/Antynea/grub-btrfs # #
# # # Purpose:
# Purpose: Include btrfs snapshots at boot options (grub-menu). # # Improves Grub by adding "btrfs snapshots" to the Grub menu.
# # # You can start your system on a "snapshot" from the Grub menu.
# What this script does: # # Supports manual snapshots, snapper ...
# Simple rollback using snapshots you made previously. # # Warning : booting on read-only snapshots can be tricky
# - Automatically List snapshots existing on root partition (btrfs). # # (Read about it, https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
# - Automatically Detect if "/boot" is in separate partition. # #
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. # # What this script does:
# - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. # # - Automatically List snapshots existing on root partition (btrfs).
# - Automatically detect snapper and use snapper's snapshot description if available. # # - Automatically Detect if "/boot" is in separate partition.
# # # - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots.
# How to customize it: # # - Automatically Create corresponding "menuentry" in grub.cfg
# - Add this lines to /etc/default/grub: # # - Automatically detect snapper and use snapper's snapshot description if available.
# # # - Automatically generate grub.cfg if you use the provided systemd service.
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" # #
# (Name appearing in the Grub menu.) # # Installation:
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" # # - Run `make install` or look into Makefile for instructions on where to put each file.
# (Add a name ahead your snapshots entries in the Grub menu.) # #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" # # Customization:
# (Show full path snapshot or only name in the Grub menu) # # Refer to config for the list of available options and their default values.
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" # # Place your configurations to /etc/default/grub-btrfs/config.
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) # #
# * GRUB_BTRFS_LIMIT="50" # # Automatically update Grub
# (Limit the number of snapshots populated in the GRUB menu.) # # If you would like Grub to automatically update when a snapshots is made or deleted:
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" # # - Use systemctl start/enable grub-btrfs.path
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). # # - grub-btrfs.path automatically (re)generates grub.cfg when a modification appears in /.snapshots folder (by default).
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) # # - If your snapshots aren't mounted in /.snapshots, you must modify the watch folder using systemctl edit grub-btrfs.path
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" # # - See https://github.com/Antynea/grub-btrfs#automatically-update-grub
# (Show snapshots found during run "grub-mkconfig") # #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" # # Special thanks for assistance and contributions:
# (Show Total of snapshots found during run "grub-mkconfig") # # - My friends
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") # # - All contributors on Github
# (Use only if you have custom kernel name.) # #
# * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") #
# (Use only if you have custom initramfs name.) #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") #
# (Use only if you have custom intel-ucode.) #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker") #
# (Ignore specific path during run "grub-mkconfig") #
# * GRUB_BTRFS_SNAPPER_CONFIG="root" #
# (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) #
# #
# - 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. #
# #
# Special thanks for assistance and contributions: #
# - My friends #
# - All contributors on Github #
# #
#########################################################################################################################################################################
set -e set -e
@@ -72,61 +45,58 @@ prefix="/usr"
exec_prefix="/usr" exec_prefix="/usr"
datarootdir="/usr/share" datarootdir="/usr/share"
sysconfdir="/etc" sysconfdir="/etc"
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
. "${sysconfdir}/default/grub" [[ -f "$grub_btrfs_config" ]] && . "$grub_btrfs_config"
. "$datarootdir/grub/grub-mkconfig_lib" . "$datarootdir/grub/grub-mkconfig_lib"
. "${sysconfdir}/default/grub"
###################################### ### Variables in /etc/default/grub-btrfs/config
### Variables in /etc/default/grub ###
######################################
## Disable Grub-btrfs (default=active) ## Disable Grub-btrfs (default=active)
grub_btrfs_disable=${GRUB_BTRFS_DISABLE:-"false"} [[ "${GRUB_BTRFS_DISABLE:-"false"}" == "true" ]] && exit 0
[[ "${grub_btrfs_disable}" == "true" ]] && exit 0
## Submenu name ## Submenu name
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"Arch Linux snapshots"} distro=$(awk -F "=" '/^NAME=/ {gsub(/"/, "", $2); print $2}' /etc/os-release)
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"}
## Prefix entry ## Prefix entry
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"} prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"}
## Show full path snapshot or only name
path_snapshot=${GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:-"true"}
## Title format
title_format=${GRUB_BTRFS_TITLE_FORMAT:-"p/d/n"}
## Kernel(s) name(s)
nkernel=("${GRUB_BTRFS_NKERNEL[@]}")
## Initramfs name(s)
ninit=("${GRUB_BTRFS_NINIT[@]}")
## Microcode(s) name(s)
microcode=("${GRUB_BTRFS_INTEL_UCODE[@]}")
## Limit snapshots to show in the Grub menu ## Limit snapshots to show in the Grub menu
limit_snap_show="${GRUB_BTRFS_LIMIT:-50}" 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"} btrfssubvolsort=(--sort="${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}")
case "${snap_list_sort}" in ## Snapper's config name
ascending) btrfssubvolsort=("--sort=+rootid");;
*) btrfssubvolsort=("--sort=-rootid")
esac
## Show snapshots found during run "grub-mkconfig"
show_snap_found=${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}
## Show Total of snapshots found during run "grub-mkconfig"
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[@]}")
## snapper's config name
snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"} snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
## Customize GRUB directory, where "grub.cfg" file is saved
grub_directory=${GRUB_BTRFS_GRUB_DIRNAME:-"/boot/grub"}
## Customize BOOT directory, where kernels/initrams/microcode is saved.
boot_directory=${GRUB_BTRFS_BOOT_DIRNAME:-"/boot"}
## Password protection management for submenu
# Protection support for submenu (--unrestricted)
case "${GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU:-"false"}" in
true) unrestricted_access_submenu="--unrestricted ";;
*) unrestricted_access_submenu=""
esac
# Authorized users (--users foo,bar)
if [ ! -z "${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS}" ] ; then
protection_authorized_users="--users ${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS} "
fi
######################## ### variables script
### variables script ### ## Probe info "Boot partition"
######################## # Boot device
## Internationalization (default : english) boot_device=$(${grub_probe} --target=device ${boot_directory})
export TEXTDOMAIN=grub-btrfs-git # hints string
export TEXTDOMAINDIR="/usr/share/locale" boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null)
## hints string # UUID of the boot partition
hs_boot=$(${grub_probe} --target="hints_string" "/boot" 2>/dev/null) boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null)
## UUID of the boot partition # Type filesystem of boot partition
boot_uuid=$(${grub_probe} --target="fs_uuid" "/boot" 2>/dev/null) boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null)
## Type filesystem of boot partition ## Probe info "Root partition"
boot_fs=$(${grub_probe} --target="fs" "/boot" 2>/dev/null) # Type filesystem of root partition
## UUID of the root partition root_fs=$(${grub_probe} --target="fs" / 2>/dev/null)
root_uuid=$(${grub_probe} "/" --target="fs_uuid" 2>/dev/null) # Root device
root_device=$(${grub_probe} --target=device /)
# UUID of the root partition
root_uuid=$(${grub_probe} --device ${root_device} --target="fs_uuid" 2>/dev/null)
## Parameters passed to the kernel ## Parameters passed to the kernel
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT" kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
## Mount point location ## Mount point location
@@ -135,382 +105,410 @@ 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
## Detect uuid requirement (lvm,btrfs...)
check_uuid_required() {
if [ "x${root_uuid}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
|| ! test -e "/dev/disk/by-uuid/${root_uuid}" \
|| ( test -e "${root_device}" && uses_abstraction "${root_device}" lvm ); then
LINUX_ROOT_DEVICE=${root_device}
else
LINUX_ROOT_DEVICE=UUID=${root_uuid}
fi
}
## Detect rootflags
detect_rootflags()
{
local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${gbgmp}/${snap_dir_name}/etc/fstab" \
| sed -E 's/^.*[[:space:]]([[:graph:]]+)$/\1/;s/,?subvol(id)?=[^,$]+//g;s/^,//')
rootflags="rootflags=${fstabflags:+$fstabflags,}${GRUB_BTRFS_ROOTFLAGS:+$GRUB_BTRFS_ROOTFLAGS,}"
}
### Error Handling
######################
### Error Handling ###
######################
print_error() print_error()
{ {
local arg="$@" local arg="$@"
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" local nothing_to_do="If you think an error has occurred , please file a bug report at \" https://github.com/Antynea/grub-btrfs \"\nNothing to do. Abort.\n"
printf "# ${arg}\n# ${nothing_to_do}" >&2 ; printf "${arg}\n${nothing_to_do}" >&2 ;
exit 0 exit 0
} }
test_btrfs() test_btrfs()
{ {
set +e [[ "$root_fs" != "btrfs" ]] && print_error "Root partition isn't a btrfs filesystem.\nThis script only supports snapshots of the btrfs filesystem."
type btrfs >/dev/null 2>&1 set +e
if [[ $? -ne 0 ]]; then type btrfs >/dev/null 2>&1
print_error "This script only supports snapshots of the btrfs filesystem, make sure you have btrfs-progs on your system." if [[ $? -ne 0 ]]; then
fi print_error "Unable to retrieve info from btrfs filesystem, make sure you have btrfs-progs on your system."
set -e fi
set -e
} }
##############
### Script ###
##############
### Script
## Create entry ## Create entry
entry() { entry()
echo "$@" >> "/boot/grub/grub-btrfs.cfg" {
# local arg="$@" echo "$@" >> "$grub_directory/grub-btrfs.cfg"
# echo "${arg}" >> "/boot/grub/grub-btrfs.cfg"
# cat << EOF >> "/boot/grub/grub-btrfs.cfg"
# ${arg}
# EOF
} }
## menu entries ## menu entries
make_menu_entries() 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
entry "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; [[ ! -f "${boot_dir}"/"${k}" ]] && continue;
kversion=${k#*"-"} kversion=${k#*"-"}
for i in "${name_initramfs[@]}"; do for i in "${name_initramfs[@]}"; do
prefix_i=${i%%"-"*} prefix_i=${i%%"-"*}
suffix_i=${i#*"-"} suffix_i=${i#*"-"}
alt_suffix_i=${i##*"-"} alt_suffix_i=${i##*"-"}
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}"; if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}"; elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
else continue ; else continue ;
fi fi
for u in "${name_microcode[@]}"; do for u in "${name_microcode[@]}"; do
if [[ -f "${boot_dir}"/"${u}" && "${i}" != "${prefix_i}-${kversion}-${alt_suffix_i}" ]] ; then if [[ "${name_microcode}" != "x" ]] ; then
entry " entry "
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{" menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else else
entry " entry "
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{" menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
fi fi
entry "\ entry "\
if [ x\$feature_all_video_module = xy ]; then if [ x\$feature_all_video_module = xy ]; then
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 ${boot_hs} ${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_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name}"\""
if [[ -f "${boot_dir}"/"${u}" && "${i}" != "${prefix_i}-${kversion}-${alt_suffix_i}" ]] ; then if [[ "${name_microcode}" != "x" ]] ; then
entry "\ entry "\
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_root_grub}/"${u}"\" \"${boot_dir_root_grub}/"${i}"\""
else else
entry "\ entry "\
echo 'Loading Initramfs: "${i}" ...' echo 'Loading Initramfs: "${i}" ...'
initrd \"${boot_dir_root_grub}/"${i}"\"" initrd \"${boot_dir_root_grub}/"${i}"\""
fi fi
entry " }" entry " }"
count_warning_menuentries=$((1+$count_warning_menuentries)) count_warning_menuentries=$((1+$count_warning_menuentries))
done done
done done
done done
entry "}" entry "}"
} }
## Trim a string from leading and trailing whitespaces ## Trim a string from leading and trailing whitespaces
trim() { trim() {
local var="$*" local var="$*"
var="${var#"${var%%[![:space:]]*}"}" var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}" var="${var%"${var##*[![:space:]]}"}"
echo -n "$var" echo -n "$var"
} }
## List of snapshots on filesystem ## List of snapshots on filesystem
snapshot_list() 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 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 2)) if [ -s "/etc/snapper/configs/$snapper_config" ]; then
local snapper_types=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 1)) printf "Info: snapper detected, using config '$snapper_config'\n" >&2
local snapper_ids=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 1))
local snapper_types=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | cut -d'|' -f 2))
IFS=$'\n' IFS=$'\n'
local snapper_descriptions=($(snapper -t 0 -c "$snapper_config" list | tail -n +3 | cut -d'|' -f 7)) local snapper_descriptions=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | rev | cut -d'|' -f 2 | rev))
fi else
printf "Warning: snapper detected but config '$snapper_config' does not exist\n" >&2
fi
fi
IFS=$'\n' IFS=$'\n'
# Parse btrfs snapshots # Parse btrfs snapshots
local entries=() local entries=()
local ids=() local ids=()
local max_entry_length=0 local max_entry_length=0
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
IFS=$oldIFS IFS=$oldIFS
snap=($snap) snap=($snap)
local snap_path_name=${snap[@]:13:${#snap[@]}} local 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" # ignore specific path during run "grub-mkconfig"
if [ ! -z "${ignore_specific_path}" ] ; then if [ ! -z "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH}" ] ; then
for isp in ${ignore_specific_path[@]} ; do for isp in ${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]} ; do
[[ "${snap_path_name}" == "${isp}"/* ]] && continue 2; [[ "${snap_path_name}" == "${isp}" ]] && continue 2;
done done
fi fi
if [ ! -z "${GRUB_BTRFS_IGNORE_PREFIX_PATH}" ] ; then
for isp in ${GRUB_BTRFS_IGNORE_PREFIX_PATH[@]} ; do
[[ "${snap_path_name}" == "${isp}"/* ]] && continue 2;
done
fi
# detect if /boot directory exists # detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue; [[ ! -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")
local entry="${snap[@]:10:2} | ${snap_path_name}" local entry="${snap[@]:10:2} | ${snap_path_name}"
entries+=("$entry") entries+=("$entry")
# Find max length of a snapshot entry, needed for pretty formatting # Find max length of a snapshot entry, needed for pretty formatting
local length="${#entry}" local length="${#entry}"
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length [[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
done done
# Find max length of a snapshot type, needed for pretty formatting # Find max length of a snapshot type, needed for pretty formatting
local max_type_length=0 local max_type_length=0
for id in "${ids[@]}"; do for 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" == "$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
fi fi
done done
done done
for i in "${!entries[@]}"; do for i in "${!entries[@]}"; do
local id="${ids[$i]}" local id="${ids[$i]}"
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" == "$id" ]]; then # remove other non numeric characters
local snapper_type=$(trim "${snapper_types[$j]}") snapper_id="${snapper_id//\*/}"
local snapper_description=$(trim "${snapper_descriptions[$j]}") snapper_id="${snapper_id//\+/}"
printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description" snapper_id="${snapper_id//-/}"
break if [[ "$snapper_id" == "$id" ]]; then
fi local snapper_type=$(trim "${snapper_types[$j]}")
done local snapper_description=$(trim "${snapper_descriptions[$j]}")
echo "$entry" printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description"
done break
fi
done
echo "$entry"
done
IFS=$oldIFS IFS=$oldIFS
} }
## Detect kernels in "/boot" ## Detect kernels in "/boot"
detect_kernel() detect_kernel()
{ {
list_kernel=() list_kernel=()
# Original kernel (auto-detect) # Original kernel (auto-detect)
for okernel in "${boot_dir}"/vmlinuz-* \ for okernel in "${boot_dir}"/vmlinuz-* \
"${boot_dir}"/vmlinux-* \ "${boot_dir}"/vmlinux-* \
"${boot_dir}"/kernel-* ; do "${boot_dir}"/kernel-* ; do
[[ ! -f "${okernel}" ]] && continue; [[ ! -f "${okernel}" ]] && continue;
list_kernel+=("$okernel") 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 "${GRUB_BTRFS_NKERNEL}" ] ; then
for ckernel in "${boot_dir}/${nkernel[@]}" ; do for ckernel in "${boot_dir}/${GRUB_BTRFS_NKERNEL[@]}" ; do
[[ ! -f "${ckernel}" ]] && continue; [[ ! -f "${ckernel}" ]] && continue;
list_kernel+=("$ckernel") list_kernel+=("$ckernel")
done done
fi fi
} }
## Detect initramfs in "/boot" ## Detect initramfs in "/boot"
detect_initramfs() detect_initramfs()
{ {
list_initramfs=() list_initramfs=()
# Original initramfs (auto-detect) # Original initramfs (auto-detect)
for oinitramfs in "${boot_dir}"/initrd.img-* \ for oinitramfs in "${boot_dir}"/initrd.img-* \
"${boot_dir}"/initrd-*.img \ "${boot_dir}"/initrd-*.img \
"${boot_dir}"/initrd-*.gz \ "${boot_dir}"/initrd-*.gz \
"${boot_dir}"/initramfs-*.img \ "${boot_dir}"/initramfs-*.img \
"${boot_dir}"/initramfs-*.gz ; do "${boot_dir}"/initramfs-*.gz ; do
[[ ! -f "${oinitramfs}" ]] && continue; [[ ! -f "${oinitramfs}" ]] && continue;
list_initramfs+=("$oinitramfs") list_initramfs+=("$oinitramfs")
done done
# Custom name initramfs in GRUB_BTRFS_NINIT # Custom name initramfs in GRUB_BTRFS_NINIT
if [ ! -z "$ninit" ] ; then if [ ! -z "${GRUB_BTRFS_NINIT}" ] ; then
for cinitramfs in "${boot_dir}/${ninit[@]}" ; do for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
[[ ! -f "${cinitramfs}" ]] && continue; [[ ! -f "${cinitramfs}" ]] && continue;
list_initramfs+=("$cinitramfs") list_initramfs+=("$cinitramfs")
done done
fi fi
} }
## Detect microcode in "/boot" ## Detect microcode in "/boot"
detect_microcode() detect_microcode()
{ {
list_ucode=() list_ucode=()
# Original intel microcode # Original intel/amd microcode (auto-detect)
for oiucode in "${boot_dir}"/intel-ucode.img ; do # See "https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html"
[[ ! -f "${oiucode}" ]] && continue; for oiucode in "${boot_dir}"/intel-uc.img \
list_ucode+=("$oiucode") "${boot_dir}"/intel-ucode.img \
done "${boot_dir}"/amd-uc.img \
"${boot_dir}"/amd-ucode.img \
"${boot_dir}"/early_ucode.cpio \
"${boot_dir}"/microcode.cpio; do
[[ ! -f "${oiucode}" ]] && continue;
list_ucode+=("$oiucode")
done
# Custom name microcode in GRUB_BTRFS_INTEL_UCODE # Custom name microcode in GRUB_BTRFS_CUSTOM_MICROCODE
if [ ! -z "$microcode" ] ; then if [ ! -z "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
for cucode in "${boot_dir}/${microcode[@]}" ; do for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
[[ ! -f "${cucode}" ]] && continue [[ ! -f "${cucode}" ]] && continue
list_ucode+=("$cucode") list_ucode+=("$cucode")
done done
fi fi
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
} }
## Show full path snapshot or only name ## Show full path snapshot or only name
path_snapshot() path_snapshot()
{ {
case "${path_snapshot}" in case "${GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:-"true"}" in
true) name_snapshot=("${snap_full_name}");; true) name_snapshot=("${snap_full_name}");;
*) name_snapshot=("${snap_full_name#*"/"}") *) name_snapshot=("${snap_full_name#*"/"}")
esac esac
} }
## Title format in grub-menu ## Title format in grub-menu
title_format() title_format()
{ {
case "${title_format}" in case "${GRUB_BTRFS_TITLE_FORMAT:-"p/d/n"}" in
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}";;
*) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}" *) 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
boot_bounded() boot_bounded()
{ {
# Initialize menu entries # Initialize menu entries
IFS=$'\n' IFS=$'\n'
for item in $(snapshot_list); do for item in $(snapshot_list); do
# fix: limit_snap_show=0 [[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
[[ ${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")" 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")"
boot_dir="$gbgmp/$snap_dir_name$boot_directory"
boot_dir="$gbgmp/$snap_dir_name/boot" # Kernel (Original + custom kernel)
# Kernel (Original + custom kernel) detect_kernel
detect_kernel if [ -z "${list_kernel}" ]; then continue; fi
if [ -z "${list_kernel}" ]; then continue; fi name_kernel=("${list_kernel[@]##*"/"}")
name_kernel=("${list_kernel[@]##*"/"}") # Detect rootflags
# Initramfs (Original + custom initramfs) detect_rootflags
detect_initramfs # Initramfs (Original + custom initramfs)
if [ -z "${list_initramfs}" ]; then continue; fi detect_initramfs
name_initramfs=("${list_initramfs[@]##*"/"}") if [ -z "${list_initramfs}" ]; then continue; fi
# microcode (intel-ucode + custom microcode) name_initramfs=("${list_initramfs[@]##*"/"}")
detect_microcode # microcode (auto-detect + custom microcode)
name_microcode=("${list_ucode[@]##*"/"}") detect_microcode
# show snapshot found during run "grub-mkconfig" name_microcode=("${list_ucode[@]##*"/"}")
if [[ "${show_snap_found}" = "true" ]]; then # show snapshot found during run "grub-mkconfig"
printf $"# Found snapshot: %s\n" "$item" >&2 ; if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
fi printf "Found snapshot: %s\n" "$item" >&2 ;
# Show full path snapshot or only name fi
path_snapshot # Show full path snapshot or only name
# Title format in grub-menu path_snapshot
title_format # Title format in grub-menu
# convert /boot directory to root of GRUB (e.g /boot become /) title_format
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" # convert /boot directory to root of GRUB (e.g /boot become /)
# Make menuentries boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
make_menu_entries # Make menuentries
### Limit snapshots found during run "grub-mkconfig" make_menu_entries
count_limit_snap=$((1+$count_limit_snap)) ### Limit snapshots found during run "grub-mkconfig"
[[ $count_limit_snap -ge $limit_snap_show ]] && break; count_limit_snap=$((1+$count_limit_snap))
# Limit generation of menuentries if exceeds 250 [[ $count_limit_snap -ge $limit_snap_show ]] && break;
# [[ $count_warning_menuentries -ge 250 ]] && break; # Limit generation of menuentries if exceeds 250
done # [[ $count_warning_menuentries -ge 250 ]] && break;
IFS=$oldIFS done
IFS=$oldIFS
} }
boot_separate() boot_separate()
{ {
boot_dir="/boot" boot_dir="${boot_directory}"
# convert /boot directory to root of GRUB (e.g /boot become /) # convert /boot directory to root of GRUB (e.g /boot become /)
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
# Kernel (Original + custom kernel) # Kernel (Original + custom kernel)
detect_kernel detect_kernel
if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
name_kernel=("${list_kernel[@]##*"/"}") name_kernel=("${list_kernel[@]##*"/"}")
# Initramfs (Original + custom initramfs)
# Initramfs (Original + custom initramfs) detect_initramfs
detect_initramfs if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi
if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi name_initramfs=("${list_initramfs[@]##*"/"}")
name_initramfs=("${list_initramfs[@]##*"/"}") # microcode (auto-detect + custom microcode)
detect_microcode
# microcode (auto-detect + custom microcode) name_microcode=("${list_ucode[@]##*"/"}")
detect_microcode
name_microcode=("${list_ucode[@]##*"/"}")
# Initialize menu entries # Initialize menu entries
IFS=$'\n' IFS=$'\n'
for item in $(snapshot_list); do for item in $(snapshot_list); do
# fix: limit_snap_show=0 [[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
[[ ${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")" 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")" # Detect rootflags
# show snapshot found during run "grub-mkconfig" detect_rootflags
if [[ "${show_snap_found}" = "true" ]]; then # show snapshot found during run "grub-mkconfig"
printf $"# Found snapshot: %s\n" "$item" >&2 ; if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
fi printf "Found snapshot: %s\n" "$item" >&2 ;
# Show full path snapshot or only name fi
path_snapshot # Show full path snapshot or only name
# Title format in grub-menu path_snapshot
title_format # Title format in grub-menu
# Make menuentries title_format
make_menu_entries # Make menuentries
# Limit snapshots found during run "grub-mkconfig" make_menu_entries
count_limit_snap=$((1+$count_limit_snap)) # Limit snapshots found during run "grub-mkconfig"
[[ $count_limit_snap -ge $limit_snap_show ]] && break; count_limit_snap=$((1+$count_limit_snap))
# Limit generation of menuentries if exceeds 250 [[ $count_limit_snap -ge $limit_snap_show ]] && break;
# [[ $count_warning_menuentries -ge 250 ]] && break; # Limit generation of menuentries if exceeds 250
done # [[ $count_warning_menuentries -ge 250 ]] && break;
IFS=$oldIFS done
IFS=$oldIFS
} }
### Start ### ### Start
printf "###### - Grub-btrfs: Snapshot detection started - ######\n" >&2 ; printf "Detecting snapshots ...\n" >&2 ;
# if btrfs prog isn't installed, exit # Only support btrfs snapshots
test_btrfs test_btrfs
# Delete existing config # Delete existing config
#rm -f --preserve-root "/boot/grub/grub-btrfs.cfg" #rm -f --preserve-root "$grub_directory/grub-btrfs.cfg"
> "/boot/grub/grub-btrfs.cfg" > "$grub_directory/grub-btrfs.cfg"
# Create mount point then mounting # Create mount point then mounting
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp [[ ! -d $gbgmp ]] && mkdir -p $gbgmp
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/ mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
@@ -518,33 +516,38 @@ mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
count_warning_menuentries=0 count_warning_menuentries=0
# Count snapshots # Count snapshots
count_limit_snap=0 count_limit_snap=0
# detect uuid requirement
check_uuid_required
# Detects if /boot is a separate partition # Detects if /boot is a separate partition
if [[ "$root_uuid" != "$boot_uuid" ]]; then if [[ "${GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION:-"false"}" == "true" ]]; then
printf "# Info: Separate boot partition detected \n" >&2 ; printf "Info: Override boot partition detection : enable \n" >&2 ;
boot_separate boot_separate
else else
printf "# Info: Separate boot partition not detected \n" >&2 ; if [[ "$root_uuid" != "$boot_uuid" ]]; then
boot_bounded printf "Info: Separate boot partition detected \n" >&2 ;
boot_separate
else
printf "Info: Separate boot partition not detected \n" >&2 ;
boot_bounded
fi
fi fi
# unmounting mount point # unmounting mount point
umount $gbgmp umount $gbgmp
# Show warn, menuentries exceeds 250 entries # 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 ; [[ $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 ; # printf "menuentries = $count_warning_menuentries \n" >&2 ;
# Show total found snapshots # Show total found snapshots
if [[ "${show_total_snap_found}" = "true" && ! -z "${count_limit_snap}" && "${count_limit_snap}" != "0" ]]; then if [[ "${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}" = "true" && ! -z "${count_limit_snap}" && "${count_limit_snap}" != "0" ]]; then
printf "# Found ${count_limit_snap} snapshot(s)\n" >&2 ; printf "Found ${count_limit_snap} snapshot(s)\n" >&2 ;
fi fi
# if no snapshot found, exit # if no snapshot found, exit
if [[ "${count_limit_snap}" = "0" || -z "${count_limit_snap}" ]]; then if [[ "${count_limit_snap}" = "0" || -z "${count_limit_snap}" ]]; then
print_error "No snapshots found." print_error "No snapshots found."
fi fi
root_grub="$(make_system_path_relative_to_its_root /boot/grub)"
# Make a submenu in GRUB (grub.cfg) # Make a submenu in GRUB (grub.cfg)
cat << EOF cat << EOF
submenu '${submenuname}' { submenu '${submenuname}' ${protection_authorized_users}${unrestricted_access_submenu}{
configfile "${root_grub}/grub-btrfs.cfg" configfile "\${prefix}/grub-btrfs.cfg"
} }
EOF EOF
printf "###### - Grub-btrfs: Snapshot detection ended - ######\n" >&2 ; ### End
### End ###

60
Makefile Normal file
View File

@@ -0,0 +1,60 @@
PKGNAME ?= grub-btrfs
PREFIX ?= /usr
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
LIB_DIR = $(DESTDIR)$(PREFIX)/lib
.PHONY: install uninstall help
install:
@install -Dm755 -t "$(DESTDIR)/etc/grub.d/" 41_snapshots-btrfs
@install -Dm644 -t "$(DESTDIR)/etc/default/grub-btrfs/" config
@install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.service
@install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfs.path
@install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE
@# Arch Linux like distros only :
@if command -V mkinitcpio >/dev/null 2>&1; then \
install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-install" "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"; \
install -Dm644 "initramfs/Arch Linux/overlay_snap_ro-hook" "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"; \
fi
@install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md
@install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
uninstall:
@grub_dirname="$$(grep -oP '^[[:space:]]*GRUB_BTRFS_GRUB_DIRNAME=\K.*' "$(DESTDIR)/etc/default/grub-btrfs/config" | sed "s|\s*#.*||;s|(\s*\(.\+\)\s*)|\1|;s|['\"]||g")"; \
rm -f "$${grub_dirname:-/boot/grub}/grub-btrfs.cfg"
@rm -f "$(DESTDIR)/etc/default/grub-btrfs/config"
@rm -f "$(DESTDIR)/etc/grub.d/41_snapshots-btrfs"
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.service"
@rm -f "$(LIB_DIR)/systemd/system/grub-btrfs.path"
@rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"
@rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"
@# Arch Linux unlike distros only :
@if ! command -V mkinitcpio >/dev/null 2>&1; then \
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio/install" || :; \
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio/hooks" || :; \
rmdir --ignore-fail-on-non-empty "$(LIB_DIR)/initcpio" || :; \
fi
@rm -f "$(SHARE_DIR)/doc/$(PKGNAME)/README.md"
@rm -f "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"
@rm -f "$(SHARE_DIR)/licenses/$(PKGNAME)/LICENSE"
@rmdir --ignore-fail-on-non-empty "$(SHARE_DIR)/doc/$(PKGNAME)/" || :
@rmdir --ignore-fail-on-non-empty "$(SHARE_DIR)/licenses/$(PKGNAME)/" || :
@rmdir --ignore-fail-on-non-empty "$(DESTDIR)/etc/default/grub-btrfs" || :
help:
@echo
@echo "Usage: $(MAKE) [ <parameter>=<value> ... ] [ <action> ]"
@echo
@echo " actions: install"
@echo " uninstall"
@echo " help"
@echo
@echo " parameters | description | defaults"
@echo " -----------+--------------------------------+----------------------------"
@echo " DESTDIR | install destination | <unset>"
@echo " PREFIX | system tree prefix | '/usr'"
@echo " SHARE_DIR | shared data location | '\$$(DESTDIR)\$$(PREFIX)/share'"
@echo " LIB_DIR | system libraries location | '\$$(DESTDIR)\$$(PREFIX)/lib'"
@echo " PKGNAME | name of the ditributed package | 'grub-btrfs'"
@echo

150
README.md
View File

@@ -1,119 +1,79 @@
[![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/releases)
![](https://img.shields.io/github/license/Antynea/grub-btrfs.svg)
## grub-btrfs ## grub-btrfs
This is a version 3.xx of grub-btrfs This is a version 4.xx of grub-btrfs
##### BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt ##### BTC donation address: `1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt`
## ##
### Description ### Description
Improves Grub by adding "btrfs snapshots" to the Grub menu.
You can start your system on a "snapshot" from the Grub menu.
Supports manual snapshots, snapper, timeshift ...
##### Warning: booting on read-only snapshots can be tricky
If you choose to do it, `/var/log` or even `/var` must be on a separate subvolume.
Otherwise, make sure your snapshots are writeable.
See [this ticket](https://github.com/Antynea/grub-btrfs/issues/92) for more info.
This project includes its own solution.
Refer to the [documentation](https://github.com/Antynea/grub-btrfs/blob/master/initramfs/readme.md).
grub-btrfs, Include btrfs snapshots at boot options. (grub menu)
## ##
### What does grub-btrfs v3.xx do : ### What does grub-btrfs v4.xx do :
Simple rollback using snapshots you made previously.
* Automatically List snapshots existing on root partition (btrfs). * Automatically List snapshots existing on root partition (btrfs).
* Automatically Detect if "/boot" is in separate partition. * Automatically Detect if "/boot" is in separate partition.
* Automatically Detect kernel, initramfs and intel/amd microcode in "/boot" directory on snapshots.
* Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. * Automatically Create corresponding "menuentry" in `grub.cfg`
* 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.
* Automatically generate `grub.cfg` if you use the provided systemd service.
## ##
### How to customize it: ### Installation :
#### Arch Linux
You have the possibility to modify many parameters. ```
Add this lines to /etc/default/grub: pacman -S grub-btrfs
```
* GRUB_BTRFS_SUBMENUNAME="Arch Linux Snapshots" #### Manual
(Name menu appearing in grub.) * Run `make install` or look into Makefile for instructions on where to put each file.
* GRUB_BTRFS_PREFIXENTRY="Snapshot:" NOTE: Generate your Grub menu after installation for the changes to take effect.
On Arch Linux use `grub-mkconfig -o /boot/grub/grub.cfg`.
(Add a name ahead your snapshots entries.) ##
### Customization:
* GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true"
(Show full path snapshot or only name, weird reaction with snapper)
* GRUB_BTRFS_TITLE_FORMAT="p/d/n"
(Custom title, shows/hides p"prefix" d"date" n"name" in grub-menu, separator "/", custom order available) You have the possibility to modify many parameters in `/etc/default/grub-btrfs/config`.
See [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) for more information.
* GRUB_BTRFS_NKERNEL=("kernel-custom")
(Use it only if you have a custom kernel name)
* GRUB_BTRFS_NINIT=("initramfs-custom.img" "initrd.img-custom")
(Use it only if you have a custom initramfs name)
* GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img")
(Use it only if you have custom intel-ucode)
* GRUB_BTRFS_LIMIT="50"
(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 number of snapshots found during run "grub-mkconfig")
* GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker")
(Ignore specific path during run "grub-mkconfig")
* GRUB_BTRFS_SNAPPER_CONFIG="root"
(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 )
grub-btrfs automatically generates snapshots entries.
You will see it appear differents entries (e.g : Snapshot: 2018-01-03 15:08:41 @test1 )
## ##
### Automatically update grub ### Automatically update grub
If you would like Grub to automatically update when a snapshot is made or deleted:
* Use `systemctl start/enable grub-btrfs.path`.
* `grub-btrfs.path` automatically (re)generates `grub.cfg` when a modification appears in `/.snapshots` folder (by default).
* If your snapshots aren't mounted in `/.snapshots`, you must modify the watch folder using `systemctl edit grub-btrfs.path`.
* For example: Timeshift mount its snapshots in `/run/timeshift/backup/timeshift-btrfs/snapshots` folder.
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: Use `systemctl edit grub-btrfs.path`.
Then wrote:
- `/etc/systemd/system/snapper-timeline.service.d/` ```
- `/etc/systemd/system/snapper-cleanup.service.d/` [Path]
PathModified=/run/timeshift/backup/timeshift-btrfs/snapshots
Once the configuration files are in place, `systemctl daemon-reload` should be run to reload the units and make the changes active. ```
and finally save.
## * You can view your change to `systemctl cat grub-btrfs.path`.
### Discussion * To revert change use `systemctl revert grub-btrfs.path`.
Pour les francophones : https://forums.archlinux.fr/viewtopic.php?f=18&t=17177 ##### Warning:
by default, `grub-mkconfig` command is used.
Might be `grub2-mkconfig` on some systems (Fedora ...).
Edit `GRUB_BTRFS_MKCONFIG` variable in `/etc/default/grub-btrfs/config` file to reflect this.
## ##
### Special thanks for assistance and contributions ### Special thanks for assistance and contributions
* [maximbaz](https://github.com/maximbaz) * [maximbaz](https://github.com/maximbaz)
* [crossroads1112](https://github.com/crossroads1112) * [All contributors](https://github.com/Antynea/grub-btrfs/graphs/contributors)
* [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)
## ##

122
config Normal file
View File

@@ -0,0 +1,122 @@
#!/usr/bin/env bash
# Disable grub-btrfs.
# Default: "false"
#GRUB_BTRFS_DISABLE="true"
# Name appearing in the Grub menu.
# Default: "Use distribution information from /etc/os-release."
#GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots"
# Add a name ahead your snapshots entries in the Grub menu.
# Default: "Snapshot:"
#GRUB_BTRFS_PREFIXENTRY="Snapshot:"
# Show full path snapshot or only name in the Grub menu, weird reaction with snapper.
# Default: "true"
#GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="false"
# Custom title.
# shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available.
# Default: "p/d/n"
#GRUB_BTRFS_TITLE_FORMAT="p/d/n"
# Limit the number of snapshots populated in the GRUB menu.
# Default: "50"
#GRUB_BTRFS_LIMIT="50"
# Sort the found subvolumes by "ogeneration" or "generation" or "path" or "rootid".
# # See Sorting section to https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-subvolume#SUBCOMMAND
# "-rootid" means list snapshot by new ones first.
# Default: "-rootid"
#GRUB_BTRFS_SUBVOLUME_SORT="+ogen,-gen,path,rootid"
# Show snapshots found during run "grub-mkconfig"
# Default: "true"
#GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"
# Show Total of snapshots found during run "grub-mkconfig"
# Default: "true"
#GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true"
# By default, "grub-btrfs" automatically detects most existing kernels.
# If you have one or more custom kernels, you can add them here.
# Default: ("")
#GRUB_BTRFS_NKERNEL=("kernel-custom" "vmlinux-custom")
# By default, "grub-btrfs" automatically detects most existing initramfs.
# If you have one or more custom initramfs, you can add them here.
# Default: ("")
#GRUB_BTRFS_NINIT=("initramfs-custom.img" "initrd-custom.img" "otherinit-custom.gz")
# By default, "grub-btrfs" automatically detects most existing microcodes.
# If you have one or more custom microcodes, you can add them here.
# Default: ("")
#GRUB_BTRFS_CUSTOM_MICROCODE=("custom-ucode.img" "custom-uc.img "custom_ucode.cpio")
# Comma seperated mount options to be used when booting a snapshot.
# They can be defined here as well as in the "/" line inside the respective snapshots'
# "/etc/fstab" files. Mount options found in both places are combined, and this variable
# takes priority over `fstab` entries.
# NB: Do NOT include "subvol=..." or "subvolid=..." here.
# Default: ""
#GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"
# Ignore specific path during run "grub-mkconfig".
# Only exact paths are ignored.
# e.g : if `specific path` = @, only `@` snapshot will be ignored.
# Default: ("@")
GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@")
# Ignore prefix path during run "grub-mkconfig".
# Any path starting with the specified string will be ignored.
# e.g : if `prefix path` = @, all snapshots beginning with "@/..." will be ignored.
# Default: ("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")
# By default "grub-btrfs" automatically detects your boot partition,
# either located at the system root or on a separate partition,
# but cannot detect if it is in a subvolume.
# Change to "true" if you have a boot partition in a different subvolume.
# Default: "false"
#GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"
# Location of the folder containing the "grub.cfg" file.
# Use by grub-btrfs to save the file "grub-btrfs.cfg".
# Might be grub2 on some systems.
# For example, on Fedora with EFI : "/boot/efi/EFI/fedora"
# Default: "/boot/grub"
#GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"
# Location of kernels/initramfs/microcode.
# Use by "grub-btrfs" to detect the boot partition and the location of kernels/initrafms/microcodes.
# Default: "/boot"
#GRUB_BTRFS_BOOT_DIRNAME="/boot"
# Name/path of grub-mkconfig command, use by "grub-btrfs.service"
# Might be 'grub2-mkconfig' on some systems (Fedora ...)
# Default paths are /sbin:/bin:/usr/sbin:/usr/bin,
# if your path is missing, report it on the upstream project.
# For example, on Fedora : "/sbin/grub2-mkconfig"
# You can use only name or full path.
# Default: grub-mkconfig
#GRUB_BTRFS_MKCONFIG=/usr/bin/grub2-mkconfig
# Snapper
# Snapper's config name to use
# Default: "root"
#GRUB_BTRFS_SNAPPER_CONFIG="root"
# Password protection management for submenu,snapshots
# Refer to the Grub documentation https://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation
# and this comment https://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660
#
# Add authorized usernames separate by comma (foo,bar)
# When Grub's password protection is enabled, the superuser is authorized by default, it isn't necessary to add it
# Default: ""
#GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="foo,bar"
#
# Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
# doesn't work if GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS isn't empty
# Default: "false"
#GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"

8
grub-btrfs.path Normal file
View File

@@ -0,0 +1,8 @@
[Unit]
Description=Monitors for new snapshots
[Path]
PathModified=/.snapshots
[Install]
WantedBy=multi-user.target

11
grub-btrfs.service Normal file
View File

@@ -0,0 +1,11 @@
[Unit]
Description=Regenerate grub-btrfs.cfg
[Service]
Type=oneshot
# Set the possible paths for `grub-mkconfig`
Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin"
# Load environment variables from the configuration
EnvironmentFile=/etc/default/grub-btrfs/config
# Regenerate just '/boot/grub/grub-btrfs.cfg' if it exists and is not empty, else regenerate the whole grub menu
ExecStart=bash -c 'if [ -s "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub-btrfs.cfg" ]; then /etc/grub.d/41_snapshots-btrfs; else ${GRUB_BTRFS_MKCONFIG:-grub-mkconfig} -o ${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}/grub.cfg; fi'

View File

@@ -0,0 +1,15 @@
#!/usr/bin/ash
run_latehook() {
local root_mnt="/new_root"
local current_dev=$(resolve_device "$root"); # resolve devices for blkid
if [[ $(blkid "${current_dev}" -s TYPE -o value) = "btrfs" ]] && [[ $(btrfs property get ${root_mnt} ro) != "ro=false" ]]; then # run only on a read only snapshot
local lower_dir=$(mktemp -d -p /)
local ram_dir=$(mktemp -d -p /)
mount --move ${root_mnt} ${lower_dir} # move new_root to lower_dir
mount -t tmpfs cowspace ${ram_dir} #meuh!!! space, you can't test !
mkdir -p ${ram_dir}/upper
mkdir -p ${ram_dir}/work
mount -t overlay -o lowerdir=${lower_dir},upperdir=${ram_dir}/upper,workdir=${ram_dir}/work rootfs ${root_mnt}
fi
}

View File

@@ -0,0 +1,18 @@
#!/bin/bash
build() {
add_module btrfs
add_module overlay
add_binary btrfs
add_binary btrfsck
add_binary blkid
add_runscript
}
help() {
cat <<HELPEOF
This hook uses overlayfs to boot on a read only snapshot.
HELPEOF
}
# vim: set ft=sh ts=4 sw=4 et:

45
initramfs/readme.md Normal file
View File

@@ -0,0 +1,45 @@
### Description :
Booting on a snapshot in read-only mode can be tricky.
An elegant way is to boot this snapshot using overlayfs (included in the kernel ≥ 3.18).
Using overlayfs, the booted snapshot will behave like a live-cd in non-persistent mode.
The snapshot will not be modified, the system will be able to boot correctly, because a writeable folder will be included in the ram.
(no more problems due to `/var` not open for writing)
Any changes in this system thus started will be lost when the system is rebooted/shutdown.
To do this, it is necessary to modify the initramfs.
This means that any snapshot that does not include this modified initramfs will not be able to benefit from it.
(except for separate boot partitions)
#
### Installation :
#### Arch Linux
1.
`Pacman -S grub-btrfs`
Or if you use git
copy the `overlay_snap_ro-install` file to `/etc/initcpio/install/grub-btrfs-overlayfs`
copy the `overlay_snap_ro-hook` file to `/etc/initcpio/hooks/grub-btrfs-overlayfs`
You must rename the files. (I did it above)
For example :
`overlay_snap_ro-install` to `grub-btrfs-overlayfs`
`overlay_snap_ro-hook` to `grub-btrfs-overlayfs`
Keep in mind that the files must have exactly the same name to ensure a match.
2.
Edit the file `/etc/mkinitcpio.conf`
Added hook `grub-btrfs-overlayfs` at the end of the line `HOOKS`.
For example :
`HOOKS=(base udev autodetect modconf block filesystems keyboard fsck grub-btrfs-overlayfs)`
You notice that the name of the `hook` must match the name of the 2 installed files. (don't forget it)
3.
Re-generate your initramfs
`mkinitcpio -P` (option -P means, all preset present in `/etc/mkinitcpio.d`)
#### Other distribution
Refer to your distribution's documentation
or contribute to this project to add a paragraph.
#

Binary file not shown.