Compare commits

...

68 Commits
2.2 ... 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
Antynea
b8325cf134 Fix: some functions doesn't work as expected (#48)
* Fix: Title format in grub-menu

function: 
- title_format , doesn't work as expected

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

* Update header

- Add Github link
- Clear up some explanations

* Fix: path to grub-mkconfig_lib

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

* Fix: matches kernel & initramfs

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

GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="true" 
Doesn't exist anymore

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

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

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

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

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

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

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

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

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

Purge some obsolete code

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

View File

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

View File

@@ -1,128 +1,102 @@
#! /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
# # #
# Purpose: Include btrfs snapshots at boot options (grub-menu). # # Purpose:
# # # Improves Grub by adding "btrfs snapshots" to the Grub menu.
# What this script does: # # You can start your system on a "snapshot" from the Grub menu.
# Simple rollback using snapshots you made previously. # # Supports manual snapshots, snapper ...
# - Automatically List snapshots existing on root partition (btrfs). # # Warning : booting on read-only snapshots can be tricky
# - Automatically Detect if "/boot" is in separate partition. # # (Read about it, https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
# - 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. # # What this script does:
# - Automatically detect snapper and use snapper's snapshot description if available. # # - Automatically List snapshots existing on root partition (btrfs).
# # # - Automatically Detect if "/boot" is in separate partition.
# How to use it: # # - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots.
# - Add this lines to /etc/default/grub: # # - Automatically Create corresponding "menuentry" in grub.cfg
# # # - Automatically detect snapper and use snapper's snapshot description if available.
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" # # - Automatically generate grub.cfg if you use the provided systemd service.
# (Name appearing in the Grub menu.) # #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" # # Installation:
# (Add a name ahead your snapshots entries in the Grub menu.) # # - Run `make install` or look into Makefile for instructions on where to put each file.
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" # #
# (Show full path snapshot or only name in the Grub menu) # # Customization:
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" # # Refer to config for the list of available options and their default values.
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) # # Place your configurations to /etc/default/grub-btrfs/config.
# * GRUB_BTRFS_LIMIT="100" # #
# (Limit the number of snapshots populated in the GRUB menu.) # # Automatically update Grub
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" # # If you would like Grub to automatically update when a snapshots is made or deleted:
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). # # - Use systemctl start/enable grub-btrfs.path
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) # # - grub-btrfs.path automatically (re)generates grub.cfg when a modification appears in /.snapshots folder (by default).
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" # # - If your snapshots aren't mounted in /.snapshots, you must modify the watch folder using systemctl edit grub-btrfs.path
# (Show snapshots found during run "grub-mkconfig") # # - See https://github.com/Antynea/grub-btrfs#automatically-update-grub
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" # #
# (Show Total of snapshots found during run "grub-mkconfig") # # Special thanks for assistance and contributions:
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") # # - My friends
# (Use only if you have custom kernel name or auto-detect failed.) # # - All contributors on Github
# * 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 set -e
#prefix="/usr" prefix="/usr"
#exec_prefix="${prefix}" exec_prefix="/usr"
datarootdir="/usr/share" datarootdir="/usr/share"
#datadir="${datarootdir}"
sysconfdir="/etc" sysconfdir="/etc"
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
. "${datarootdir}/grub/grub-mkconfig_lib" [[ -f "$grub_btrfs_config" ]] && . "$grub_btrfs_config"
. "$datarootdir/grub/grub-mkconfig_lib"
. "${sysconfdir}/default/grub" . "${sysconfdir}/default/grub"
###################################### ### Variables in /etc/default/grub-btrfs/config
### Variables in /etc/default/grub ### ## Disable Grub-btrfs (default=active)
###################################### [[ "${GRUB_BTRFS_DISABLE:-"false"}" == "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 ## Limit snapshots to show in the Grub menu
path_snapshot=${GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:-"true"} limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
## 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 to show in the Grub menu
limit_snap_show="${GRUB_BTRFS_LIMIT:-100}"
## 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[@]}")
## 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"} 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
######################## ## Probe info "Boot partition"
### variables script ### # Boot device
######################## boot_device=$(${grub_probe} --target=device ${boot_directory})
## Internationalization (default : english) # hints string
export TEXTDOMAIN=grub-btrfs-git boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null)
export TEXTDOMAINDIR="/usr/share/locale" # UUID of the boot partition
## hints string boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null)
hs_boot=$(${grub_probe} --target="hints_string" "/boot" 2>/dev/null) # Type filesystem of boot partition
## UUID of the boot partition boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null)
boot_uuid=$(${grub_probe} --target="fs_uuid" "/boot" 2>/dev/null) ## Probe info "Root partition"
## Type filesystem of boot partition # Type filesystem of root partition
boot_fs=$(${grub_probe} --target="fs" "/boot" 2>/dev/null) root_fs=$(${grub_probe} --target="fs" / 2>/dev/null)
## UUID of the root partition # Root device
root_uuid=$(${grub_probe} "/" --target="fs_uuid" 2>/dev/null) 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
@@ -131,363 +105,449 @@ gbgmp=$(mktemp -d)
CLASS="--class snapshots --class gnu-linux --class gnu --class os" CLASS="--class snapshots --class gnu-linux --class gnu --class os"
## save IFS ## save IFS
oldIFS=$IFS oldIFS=$IFS
## boot_dir (auto-detect if /boot is separate partition or not) ## Detect uuid requirement (lvm,btrfs...)
boot_dir() 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()
{ {
boot_dir="$gbgmp/$snap_dir_name/boot" local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${gbgmp}/${snap_dir_name}/etc/fstab" \
[[ "$root_uuid" != "$boot_uuid" ]] && boot_dir="/boot" | sed -E 's/^.*[[:space:]]([[:graph:]]+)$/\1/;s/,?subvol(id)?=[^,$]+//g;s/^,//')
echo "$boot_dir" rootflags="rootflags=${fstabflags:+$fstabflags,}${GRUB_BTRFS_ROOTFLAGS:+$GRUB_BTRFS_ROOTFLAGS,}"
} }
### Error Handling
print_error()
{
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 \"\nNothing to do. Abort.\n"
printf "${arg}\n${nothing_to_do}" >&2 ;
exit 0
}
############## test_btrfs()
### Script ### {
############## [[ "$root_fs" != "btrfs" ]] && print_error "Root partition isn't a btrfs filesystem.\nThis script only supports snapshots of the btrfs filesystem."
set +e
type btrfs >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
print_error "Unable to retrieve info from btrfs filesystem, make sure you have btrfs-progs on your system."
fi
set -e
}
### BEGIN auto detect ### ### Script
## Create entry
entry()
{
echo "$@" >> "$grub_directory/grub-btrfs.cfg"
}
## menu entries ## menu entries
snapshots_entry() make_menu_entries()
{ {
## \" required for snap,kernels,init,microcode with space in their name ## \" required for snap,kernels,init,microcode with space in their name
echo " submenu '$title_menu' { entry "submenu '$title_menu' {
submenu '---> $title_menu <---' { echo } submenu '---> $title_menu <---' { echo }"
" for k in "${name_kernel[@]}"; do
for k in "${name_kernel[@]}"; do [[ ! -f "${boot_dir}"/"${k}" ]] && continue;
for i in "${name_initramfs[@]}"; do kversion=${k#*"-"}
for u in "${name_microcode[@]}"; do for i in "${name_initramfs[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then prefix_i=${i%%"-"*}
echo "\ suffix_i=${i#*"-"}
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{" alt_suffix_i=${i##*"-"}
else if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
echo "\ elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{" elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
fi elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
echo "\ else continue ;
$(save_default_entry) fi
if [ x\$feature_all_video_module = xy ]; then for u in "${name_microcode[@]}"; do
insmod all_video if [[ "${name_microcode}" != "x" ]] ; then
fi entry "
set gfxpayload=keep menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
insmod ${boot_fs} else
if [ x\$feature_platform_search_hint = xy ]; then entry "
search --no-floppy --fs-uuid --set=root ${hs_boot} ${boot_uuid} menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else fi
search --no-floppy --fs-uuid --set=root ${boot_uuid} entry "\
fi if [ x\$feature_all_video_module = xy ]; then
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"' insmod all_video
echo 'Loading Kernel: "${k}" ...' fi
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}" set gfxpayload=keep
if [ -f "$(boot_dir)"/"${u}" ] ; then insmod ${boot_fs}
echo "\ if [ x\$feature_platform_search_hint = xy ]; then
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...' search --no-floppy --fs-uuid --set=root ${boot_hs} ${boot_uuid}
initrd \"${boot_dir_real_path}/"${u}"\" \"${boot_dir_real_path}/"${i}"\"" else
else search --no-floppy --fs-uuid --set=root ${boot_uuid}
echo "\ fi
echo 'Loading Initramfs: "${i}" ...' echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
initrd \"${boot_dir_real_path}/"${i}"\"" echo 'Loading Kernel: "${k}" ...'
fi linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name}"\""
echo " }" if [[ "${name_microcode}" != "x" ]] ; then
done entry "\
done echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
done initrd \"${boot_dir_root_grub}/"${u}"\" \"${boot_dir_root_grub}/"${i}"\""
echo " }" else
} entry "\
echo 'Loading Initramfs: "${i}" ...'
harmonized_snapshots_entry() initrd \"${boot_dir_root_grub}/"${i}"\""
{ fi
## \" required for snap,kernels,init,microcode with space in their name entry " }"
echo " submenu '$title_menu' { count_warning_menuentries=$((1+$count_warning_menuentries))
submenu '---> $title_menu <---' { echo } done
" done
for k in "${name_kernel[@]}"; do done
version=${k#vmlinuz-} entry "}"
i=""
if [ -f "$(boot_dir)"/initramfs-"${version}".img ]; then
i=initramfs-${version}.img
else
if [ -f "$(boot_dir)"/initrd.img-"${version}" ]; then
i=initrd.img-${version}
fi
fi
for u in "${name_microcode[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
else
echo "\
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
fi
echo "\
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
set gfxpayload=keep
insmod ${boot_fs}
if [ x\$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ${hs_boot} ${boot_uuid}
else
search --no-floppy --fs-uuid --set=root ${boot_uuid}
fi
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
echo 'Loading Kernel: "${k}" ...'
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}"
if [ -f "$(boot_dir)"/"${i}" ] ; then
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
initrd \"${boot_dir_real_path}/"${u}"\" \"${boot_dir_real_path}/"${i}"\""
else
echo "\
echo 'Loading Initramfs: "${i}" ...'
initrd \"${boot_dir_real_path}/"${i}"\""
fi
fi
echo " }"
done
done
echo " }"
} }
## Trim a string from leading and trailing whitespaces ## Trim a string from leading and trailing whitespaces
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
if [ "$snap_path_name" = "DELETED" ]; then continue; fi
[[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"}
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric # Discard deleted snapshots
ids+=("$id") if [ "$snap_path_name" = "DELETED" ]; then continue; fi
[[ ${snap_path_name%%"/"*} == "<FS_TREE>" ]] && snap_path_name=${snap_path_name#*"/"}
local entry="${snap[@]:10:2} | ${snap_path_name}" # ignore specific path during run "grub-mkconfig"
entries+=("$entry") if [ ! -z "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH}" ] ; then
for isp in ${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]} ; do
[[ "${snap_path_name}" == "${isp}" ]] && continue 2;
done
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
# Find max length of a snapshot entry, needed for pretty formatting # detect if /boot directory exists
local length="${#entry}" [[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue;
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
done
# Find max length of a snapshot type, needed for pretty formatting local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
local max_type_length=0 ids+=("$id")
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 entry="${snap[@]:10:2} | ${snap_path_name}"
local id="${ids[$i]}" entries+=("$entry")
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 # 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:]]/}"
# remove other non numeric characters
snapper_id="${snapper_id//\*/}"
snapper_id="${snapper_id//\+/}"
snapper_id="${snapper_id//-/}"
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" ## Detect kernels in "/boot"
detect_kernel() detect_kernel()
{ {
## Arch original kernel (auto-detect) list_kernel=()
for akernel in "$(boot_dir)"/vmlinuz-* ; do # Original kernel (auto-detect)
list_kernel+=("$akernel") for okernel in "${boot_dir}"/vmlinuz-* \
done "${boot_dir}"/vmlinux-* \
"${boot_dir}"/kernel-* ; do
[[ ! -f "${okernel}" ]] && continue;
list_kernel+=("$okernel")
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 "${nkernel[@]}" ; do for ckernel in "${boot_dir}/${GRUB_BTRFS_NKERNEL[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${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()
{ {
## Arch original initramfs (auto-detect) list_initramfs=()
for ainitramfs in "$(boot_dir)"/initramfs-* ; do # Original initramfs (auto-detect)
list_initramfs+=("$ainitramfs") for oinitramfs in "${boot_dir}"/initrd.img-* \
done "${boot_dir}"/initrd-*.img \
"${boot_dir}"/initrd-*.gz \
"${boot_dir}"/initramfs-*.img \
"${boot_dir}"/initramfs-*.gz ; do
[[ ! -f "${oinitramfs}" ]] && continue;
list_initramfs+=("$oinitramfs")
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 "${ninit[@]}" ; do for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${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()
{ {
## Arch original intel microcode list_ucode=()
for aucode in "$(boot_dir)"/intel-ucode.img ; do # Original intel/amd microcode (auto-detect)
list_ucode+=("$aucode") # See "https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html"
done for oiucode in "${boot_dir}"/intel-uc.img \
"${boot_dir}"/intel-ucode.img \
"${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 "${microcode[@]}" ; do for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${cucode}" ]] && continue [[ ! -f "${cucode}" ]] && continue
list_ucode+=("$cucode") list_ucode+=("$cucode")
done done
fi fi
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
} }
## Show full path snapshot or only name ## Show full path snapshot or only name
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/d/n) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}";; p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";; p/d) title_menu="${prefixentry} ${snap_date_time}";;
p/d) title_menu="${prefixentry} ${snap_date_time}";; p/n) title_menu="${prefixentry} ${name_snapshot}";;
p/n) title_menu="${prefixentry} ${name_snapshot}";; d/n) title_menu="${snap_date_time} ${name_snapshot}";;
d/n) title_menu="${snap_date_time} ${name_snapshot}";; n/d) title_menu="${name_snapshot} ${snap_date_time}";;
n/d) title_menu="${name_snapshot} ${snap_date_time}";; p) title_menu="${prefixentry}";;
p) title_menu="${prefixentry}";; d) title_menu="${snap_date_time}";;
d) title_menu="${snap_date_time}";; n) title_menu="${name_snapshot}";;
n) title_menu="${name_snapshot}";; *) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}"
*) gettext_printf $"# Warning: GRUB_BTRFS_TITLE_FORMAT=${title_format}, syntax error \n" >&2 esac
esac
} }
## List of kernels, initramfs and microcode in snapshots ## List of kernels, initramfs and microcode in snapshots
list_kernels_initramfs() boot_bounded()
{ {
IFS=$'\n' # Initialize menu entries
count_limit_snap=0 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="$(trim "$snap_date_time")"
### ignore specific path during run "grub-mkconfig" boot_dir="$gbgmp/$snap_dir_name$boot_directory"
if [ ! -z "${ignore_specific_path}" ] ; then # Kernel (Original + custom kernel)
for isp in ${ignore_specific_path[@]} ; do detect_kernel
[[ "${gbgmp}"/"${snap_dir_name}" == "${gbgmp}"/"${isp}"/* ]] && continue 2; if [ -z "${list_kernel}" ]; then continue; fi
done name_kernel=("${list_kernel[@]##*"/"}")
fi # Detect rootflags
### detect if /boot directory exists detect_rootflags
[[ ! -d "$gbgmp/$snap_dir_name/boot" ]] && continue; # Initramfs (Original + custom initramfs)
### show snapshot found during run "grub-mkconfig" detect_initramfs
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)" if [ -z "${list_initramfs}" ]; then continue; fi
snap_date_time="$(trim "$snap_date_time")" name_initramfs=("${list_initramfs[@]##*"/"}")
if [[ "${show_snap_found}" = "true" ]]; then # microcode (auto-detect + custom microcode)
gettext_printf $"# Found snapshot: %s\n" "$item" >&2 ; detect_microcode
fi name_microcode=("${list_ucode[@]##*"/"}")
### Kernel (auto-detect + custom kernel) # show snapshot found during run "grub-mkconfig"
unset list_kernel if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
detect_kernel printf "Found snapshot: %s\n" "$item" >&2 ;
name_kernel=("${list_kernel[@]##*"/"}") fi
# echo "kernel = ${name_kernel[*]}" # Show full path snapshot or only name
if [[ "${harmonized_entries}" != "true" ]]; then path_snapshot
### Initramfs (autodetect + custom initramfs) # Title format in grub-menu
unset list_initramfs title_format
detect_initramfs # convert /boot directory to root of GRUB (e.g /boot become /)
name_initramfs=("${list_initramfs[@]##*"/"}") boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
# echo "initramfs = ${name_initramfs[*]}" # Make menuentries
fi make_menu_entries
### microcode (auto-detect + custom microcode) ### Limit snapshots found during run "grub-mkconfig"
unset list_ucode count_limit_snap=$((1+$count_limit_snap))
detect_microcode [[ $count_limit_snap -ge $limit_snap_show ]] && break;
name_microcode=("${list_ucode[@]##*"/"}") # Limit generation of menuentries if exceeds 250
# echo "ucode = ${name_microcode[*]}" # [[ $count_warning_menuentries -ge 250 ]] && break;
### real path to boot done
boot_dir_real_path="$(make_system_path_relative_to_its_root "$(boot_dir)")" IFS=$oldIFS
### Create menu entries
## name snapshot
path_snapshot
## title menu custom
title_format
# echo "${title_menu}"
if [[ "${harmonized_entries}" = "false" ]]; then
snapshots_entry
else
harmonized_snapshots_entry
fi
### 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
} }
### END auto detect ### boot_separate()
{
boot_dir="${boot_directory}"
# convert /boot directory to root of GRUB (e.g /boot become /)
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
### Start ### # Kernel (Original + custom kernel)
gettext_printf "###### - Grub-btrfs: Auto-detect Start - ######\n" >&2 ; detect_kernel
### create mount point and mounts if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp name_kernel=("${list_kernel[@]##*"/"}")
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/ # Initramfs (Original + custom initramfs)
### Create a menu in grub detect_initramfs
echo "submenu '${submenuname}' {" if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi
list_kernels_initramfs ; name_initramfs=("${list_initramfs[@]##*"/"}")
## show total found snapshots # microcode (auto-detect + custom microcode)
if [[ "${show_total_snap_found}" = "true" ]]; then detect_microcode
gettext_printf "# Found ${count_limit_snap} snapshot(s)\n" >&2 ; name_microcode=("${list_ucode[@]##*"/"}")
fi
## if no snapshot found, show a warning # Initialize menu entries
if [[ "${count_limit_snap}" = "0" ]]; then IFS=$'\n'
echo " submenu '---> "No snapshot found : Press ESC to return previous menu" <---' { echo } "; for item in $(snapshot_list); do
gettext_printf "# No snapshot found \n# make sure you have at least one snapshot \n# or please file a bug report at \"https://github.com/Antynea/grub-btrfs\"\n" >&2 ; [[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
fi IFS=$oldIFS
echo "}" snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
## unmount mount point snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
umount $gbgmp snap_dir_name="$(trim "$snap_dir_name")"
gettext_printf "###### - Grub-btrfs: Auto-detect End - ######\n" >&2 ; snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
### End ### snap_date_time="$(trim "$snap_date_time")"
# Detect rootflags
detect_rootflags
# show snapshot found during run "grub-mkconfig"
if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
printf "Found snapshot: %s\n" "$item" >&2 ;
fi
# Show full path snapshot or only name
path_snapshot
# Title format in grub-menu
title_format
# Make menuentries
make_menu_entries
# Limit snapshots found during run "grub-mkconfig"
count_limit_snap=$((1+$count_limit_snap))
[[ $count_limit_snap -ge $limit_snap_show ]] && break;
# Limit generation of menuentries if exceeds 250
# [[ $count_warning_menuentries -ge 250 ]] && break;
done
IFS=$oldIFS
}
### Start
printf "Detecting snapshots ...\n" >&2 ;
# Only support btrfs snapshots
test_btrfs
# Delete existing config
#rm -f --preserve-root "$grub_directory/grub-btrfs.cfg"
> "$grub_directory/grub-btrfs.cfg"
# Create mount point then mounting
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
# Count menuentries
count_warning_menuentries=0
# Count snapshots
count_limit_snap=0
# detect uuid requirement
check_uuid_required
# Detects if /boot is a separate partition
if [[ "${GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION:-"false"}" == "true" ]]; then
printf "Info: Override boot partition detection : enable \n" >&2 ;
boot_separate
else
if [[ "$root_uuid" != "$boot_uuid" ]]; then
printf "Info: Separate boot partition detected \n" >&2 ;
boot_separate
else
printf "Info: Separate boot partition not detected \n" >&2 ;
boot_bounded
fi
fi
# unmounting mount point
umount $gbgmp
# Show warn, menuentries exceeds 250 entries
[[ $count_warning_menuentries -ge 250 ]] && printf "Generated ${count_warning_menuentries} total GRUB entries. You might experience issues loading snapshots menu in GRUB.\n" >&2 ;
# printf "menuentries = $count_warning_menuentries \n" >&2 ;
# Show total found snapshots
if [[ "${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 ;
fi
# if no snapshot found, exit
if [[ "${count_limit_snap}" = "0" || -z "${count_limit_snap}" ]]; then
print_error "No snapshots found."
fi
# Make a submenu in GRUB (grub.cfg)
cat << EOF
submenu '${submenuname}' ${protection_authorized_users}${unrestricted_access_submenu}{
configfile "\${prefix}/grub-btrfs.cfg"
}
EOF
### 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

144
README.md
View File

@@ -1,115 +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 2.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 v2.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. (For custom name, see below.) * 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 use it: ### Installation :
#### Arch Linux
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" 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.
(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)
* GRUB_BTRFS_NKERNEL=("vmlinuz-linux")
(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 a 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_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 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, very useful with debian-like distributions)
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.