Compare commits

...

85 Commits
v2.0 ... v4.8.1

Author SHA1 Message Date
Kriss
2f22fd8630 [make help] mention INITCPIO switch (#137)
This commit is an expansion to :
87b816345b

Since a new `make` parameter has been introduced, it should be mentioned
in the output of the `help` target.

Also, the table is being expanded by a new column describing the type of
data that each parameter may be assigned, like paths or boolean values.
2021-01-23 20:46:14 +01:00
Antynea
88a0320d62 [Makefile] remove mkinitcpio dependency (#136)
Errata commit:
This commit has no substantive code change.
This commit is provided only to document a correction to a previous commit message.
This pertains to commit object 87b816345b

Due to improper handling, the aforementioned commit message is incorrect.
Correct message is :

[Makefile] remove `mkinitcpio` dependency

The mkinitcpio binary is not available even on Arch,  when building in a
clean environment (e.g. building distro packages in a clean chroot).

This causes the mkinitcpio hook  to not be present in the final package,
which is resolved by this commit, by adding a `make` switch. This switch
allows users to explicitely turn on inclusion of the hook.

[uninstall:] don't remove non-existent folders

This prevents some warnings being output when on a non-Archlinux system,
without a previously installed initcpio hook, a `make uninstall` is per-
formed.

These three folders should _only_ be deleted if they had been mistakenly
created during `make install`.

Co-authored-by: Kriss <kr1ss.x@yandex.com>
2021-01-23 12:02:11 +01:00
Kriss
87b816345b [Makefile] remove mkinitcpio dependency (#136)
[Makefile] remove `mkinitcpio` dependency
2021-01-17 22:25:10 +01:00
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
Maxim Baz
773a8bfb76 Support selecting snapper's config, default to 'root' (#41) 2018-04-01 21:38:22 +02:00
Antynea
1b40cfee20 Update 41_snapshots-btrfs
Update 41_snapshots-btrfs
2018-02-03 22:59:03 +01:00
Antynea
358dedc392 Update 41_snapshots-btrfs
Update 41_snapshots-btrfs
2018-02-03 22:57:04 +01:00
Antynea
55dc182b34 Update README.md 2018-02-03 22:31:43 +01:00
Nathan Parsons
23ddb063cb Add systemd service configuration for grub updating (#38)
* Add systemd service configuration for grub updating

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

* Make invoked command more universal

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

View File

@@ -1,120 +1,102 @@
#! /usr/bin/env bash
#
#
#################################################################################################################################################
# Written by: Antynea #
# #
# Purpose: Include btrfs snapshots at boot options (grub-menu). #
# #
# What this script does: #
# - Automatically List snapshots existing on root partition (btrfs). #
# - Automatically Detect if "/boot" is in separate partition. #
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custon name, see below.) #
# - Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback. #
# #
# How to use it: #
# - Add this lines to /etc/default/grub: #
# #
# * GRUB_BTRFS_SUBMENUNAME="Arch Linux snapshots" #
# (Name appearing in the Grub menu.) #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot:" #
# (Add a name ahead your snapshots entries in the Grub menu.) #
# * GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true" #
# (Show full path snapshot or only name in the Grub menu) #
# * GRUB_BTRFS_TITLE_FORMAT="p/d/n" #
# (Custom title, shows/hides p"prefix" d"date" n"name" in the Grub menu, separator "/", custom order available) #
# * GRUB_BTRFS_LIMIT="100" #
# (Limit the number of snapshots populated in the GRUB menu.) #
# * GRUB_BTRFS_SUBVOLUME_SORT="descending" #
# (Sort the found subvolumes by newest first ("descending") or oldest first ("ascending"). #
# If "ascending" is chosen then the $GRUB_BTRFS_LIMIT oldest subvolumes will populate the menu.) #
# * GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="true" #
# (Show snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND="true" #
# (Show Total of snapshots found during run "grub-mkconfig") #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") #
# (Use only if you have custom kernel name or auto-detect failed.) #
# * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") #
# (Use only if you have custom initramfs name or auto-detect failed.) #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") #
# (Use only if you have custom intel-ucode or auto-detect failed.) #
# * GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("var/lib/docker" "nosnapshot") #
# (Ignore specific path during run "grub-mkconfig") #
# * GRUB_BTRFS_CREATE_ONLY_HARMONIZED_ENTRIES="false" #
# (Create entries with matching version number instead of all possible combinations of kernel and initramfs) #
# #
# - 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) #
# #
# #
# To do: #
# #
# * Snapper support .... #
# #
#################################################################################################################################################
# Written by: Antynea
# BTC donation address: 1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt
# Github: https://github.com/Antynea/grub-btrfs
#
# Purpose:
# 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 ...
# Warning : booting on read-only snapshots can be tricky
# (Read about it, https://github.com/Antynea/grub-btrfs#warning-booting-on-read-only-snapshots-can-be-tricky)
#
# What this script does:
# - Automatically List snapshots existing on root partition (btrfs).
# - Automatically Detect if "/boot" is in separate partition.
# - Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots.
# - Automatically Create corresponding "menuentry" in grub.cfg
# - Automatically detect snapper and use snapper's snapshot description if available.
# - Automatically generate grub.cfg if you use the provided systemd service.
#
# Installation:
# - Run `make install` or look into Makefile for instructions on where to put each file.
#
# Customization:
# Refer to config for the list of available options and their default values.
# Place your configurations to /etc/default/grub-btrfs/config.
#
# Automatically update Grub
# If you would like Grub to automatically update when a snapshots 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
# - See https://github.com/Antynea/grub-btrfs#automatically-update-grub
#
# Special thanks for assistance and contributions:
# - My friends
# - All contributors on Github
#
set -e
#prefix="/usr"
#exec_prefix="${prefix}"
prefix="/usr"
exec_prefix="/usr"
datarootdir="/usr/share"
#datadir="${datarootdir}"
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"
######################################
### Variables in /etc/default/grub ###
######################################
### Variables in /etc/default/grub-btrfs/config
## Disable Grub-btrfs (default=active)
[[ "${GRUB_BTRFS_DISABLE:-"false"}" == "true" ]] && exit 0
## 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
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 to show in the Grub menu
limit_snap_show="${GRUB_BTRFS_LIMIT:-100}"
## Limit snapshots to show in the Grub menu
limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
## How to sort snapshots list
snap_list_sort=${GRUB_BTRFS_SUBVOLUME_SORT:-"descending"}
case "${snap_list_sort}" in
ascending) btrfssubvolsort=("--sort=+rootid");;
*) btrfssubvolsort=("--sort=-rootid")
btrfssubvolsort=(--sort="${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}")
## Snapper's config name
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
## 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"}
# 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 ###
########################
## Internationalization (default : english)
export TEXTDOMAIN=grub-btrfs-git
export TEXTDOMAINDIR="/usr/share/locale"
## hints string
hs_boot=$(${grub_probe} --target="hints_string" "/boot" 2>/dev/null)
## UUID of the boot partition
boot_uuid=$(${grub_probe} --target="fs_uuid" "/boot" 2>/dev/null)
## Type filesystem of boot partition
boot_fs=$(${grub_probe} --target="fs" "/boot" 2>/dev/null)
## UUID of the root partition
root_uuid=$(${grub_probe} "/" --target="fs_uuid" 2>/dev/null)
### variables script
## Probe info "Boot partition"
# Boot device
boot_device=$(${grub_probe} --target=device ${boot_directory})
# hints string
boot_hs=$(${grub_probe} --device ${boot_device} --target="hints_string" 2>/dev/null)
# UUID of the boot partition
boot_uuid=$(${grub_probe} --device ${boot_device} --target="fs_uuid" 2>/dev/null)
# Type filesystem of boot partition
boot_fs=$(${grub_probe} --device ${boot_device} --target="fs" 2>/dev/null)
## Probe info "Root partition"
# Type filesystem of root partition
root_fs=$(${grub_probe} --target="fs" / 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
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
## Mount point location
@@ -123,363 +105,449 @@ gbgmp=$(mktemp -d)
CLASS="--class snapshots --class gnu-linux --class gnu --class os"
## save IFS
oldIFS=$IFS
## boot_dir (auto-detect if /boot is separate partition or not)
boot_dir()
## 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()
{
boot_dir="$gbgmp/$snap_dir_name/boot"
[[ "$root_uuid" != "$boot_uuid" ]] && boot_dir="/boot"
echo "$boot_dir"
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
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
}
##############
### Script ###
##############
test_btrfs()
{
[[ "$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
snapshots_entry()
make_menu_entries()
{
## \" required for snap,kernels,init,microcode with space in their name
echo " submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }
"
for k in "${name_kernel[@]}"; do
for i in "${name_initramfs[@]}"; do
for u in "${name_microcode[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
else
echo "\
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
fi
echo "\
$(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)"/"${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
echo " }"
done
done
done
echo " }"
}
harmonized_snapshots_entry()
{
## \" required for snap,kernels,init,microcode with space in their name
echo " submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }
"
for k in "${name_kernel[@]}"; do
version=${k#vmlinuz-}
i=""
if [ -f "$(boot_dir)"/initramfs-"${version}".img ]; then
i=initramfs-${version}.img
else
if [ -f "$(boot_dir)"/initrd.img-"${version}" ]; then
i=initrd.img-${version}
fi
fi
for u in "${name_microcode[@]}"; do
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
else
echo "\
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid'{"
fi
echo "\
$(save_default_entry)
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
set gfxpayload=keep
insmod ${boot_fs}
if [ x\$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root ${hs_boot} ${boot_uuid}
else
search --no-floppy --fs-uuid --set=root ${boot_uuid}
fi
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
echo 'Loading Kernel: "${k}" ...'
linux \"${boot_dir_real_path}/"${k}"\" root=UUID=${root_uuid} rw rootflags=subvol=\""${snap_dir_name}"\" ${kernel_parameters}"
if [ -f "$(boot_dir)"/"${i}" ] ; then
if [ -f "$(boot_dir)"/"${u}" ] ; then
echo "\
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
initrd \"${boot_dir_real_path}/"${u}"\" \"${boot_dir_real_path}/"${i}"\""
else
echo "\
echo 'Loading Initramfs: "${i}" ...'
initrd \"${boot_dir_real_path}/"${i}"\""
fi
fi
echo " }"
done
done
echo " }"
entry "submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }"
for k in "${name_kernel[@]}"; do
[[ ! -f "${boot_dir}"/"${k}" ]] && continue;
kversion=${k#*"-"}
for i in "${name_initramfs[@]}"; do
prefix_i=${i%%"-"*}
suffix_i=${i#*"-"}
alt_suffix_i=${i##*"-"}
if [ "${kversion}" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}-fallback.img" = "${suffix_i}" ]; then i="${i}";
elif [ "${kversion}.gz" = "${suffix_i}" ]; then i="${i}";
else continue ;
fi
for u in "${name_microcode[@]}"; do
if [[ "${name_microcode}" != "x" ]] ; then
entry "
menuentry '"${k}" & "${i}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else
entry "
menuentry '"${k}" & "${i}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
fi
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 ${boot_hs} ${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_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name}"\""
if [[ "${name_microcode}" != "x" ]] ; then
entry "\
echo 'Loading Microcode & Initramfs: "${u}" "${i}" ...'
initrd \"${boot_dir_root_grub}/"${u}"\" \"${boot_dir_root_grub}/"${i}"\""
else
entry "\
echo 'Loading Initramfs: "${i}" ...'
initrd \"${boot_dir_root_grub}/"${i}"\""
fi
entry " }"
count_warning_menuentries=$((1+$count_warning_menuentries))
done
done
done
entry "}"
}
## Trim a string from leading and trailing whitespaces
trim() {
local var="$*"
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
local var="$*"
var="${var#"${var%%[![:space:]]*}"}"
var="${var%"${var##*[![:space:]]}"}"
echo -n "$var"
}
## List of snapshots on filesystem
snapshot_list()
{
# Query info from snapper if it is installed
type snapper >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
local snapper_ids=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 2))
local snapper_types=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 1))
# Query info from snapper if it is installed
type snapper >/dev/null 2>&1
if [ $? -eq 0 ]; then
if [ -s "/etc/snapper/configs/$snapper_config" ]; then
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'
local snapper_descriptions=($(snapper -t 0 list -a | tail -n +3 | cut -d'|' -f 7))
fi
IFS=$'\n'
local snapper_descriptions=($(snapper --no-dbus -t 0 -c "$snapper_config" list --disable-used-space | tail -n +3 | rev | cut -d'|' -f 2 | rev))
else
printf "Warning: snapper detected but config '$snapper_config' does not exist\n" >&2
fi
fi
IFS=$'\n'
IFS=$'\n'
# Parse btrfs snapshots
local entries=()
local ids=()
local max_entry_length=0
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
IFS=$oldIFS
snap=($snap)
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#*"/"}
# Parse btrfs snapshots
local entries=()
local ids=()
local max_entry_length=0
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
IFS=$oldIFS
snap=($snap)
local snap_path_name=${snap[@]:13:${#snap[@]}}
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
ids+=("$id")
# Discard deleted snapshots
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}"
entries+=("$entry")
# ignore specific path during run "grub-mkconfig"
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
local length="${#entry}"
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
done
# detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue;
# Find max length of a snapshot type, needed for pretty formatting
local max_type_length=0
for id in "${ids[@]}"; do
for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$id" ]]; then
local snapper_type=$(trim "${snapper_types[$j]}")
local length="${#snapper_type}"
[[ "$length" -gt "$max_type_length" ]] && max_type_length=$length
fi
done
done
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
ids+=("$id")
for i in "${!entries[@]}"; do
local id="${ids[$i]}"
local entry="${entries[$i]}"
for j in "${!snapper_ids[@]}"; do
local snapper_id="${snapper_ids[$j]//[[:space:]]/}"
if [[ "$snapper_id" -eq "$id" ]]; then
local snapper_type=$(trim "${snapper_types[$j]}")
local snapper_description=$(trim "${snapper_descriptions[$j]}")
printf -v entry "%-${max_entry_length}s | %-${max_type_length}s | %s" "$entry" "$snapper_type" "$snapper_description"
break
fi
done
echo "$entry"
done
local entry="${snap[@]:10:2} | ${snap_path_name}"
entries+=("$entry")
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_kernel()
{
## Arch original kernel (auto-detect)
for akernel in "$(boot_dir)"/vmlinuz-* ; do
list_kernel+=("$akernel")
done
list_kernel=()
# Original kernel (auto-detect)
for okernel in "${boot_dir}"/vmlinuz-* \
"${boot_dir}"/vmlinux-* \
"${boot_dir}"/kernel-* ; do
[[ ! -f "${okernel}" ]] && continue;
list_kernel+=("$okernel")
done
## Custom name kernel in GRUB_BTRFS_NKERNEL
if [ ! -z "${nkernel}" ] ; then
for ckernel in "${nkernel[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${ckernel}" ]] && continue;
list_kernel+=("$ckernel")
done
fi
# Custom name kernel in GRUB_BTRFS_NKERNEL
if [ ! -z "${GRUB_BTRFS_NKERNEL}" ] ; then
for ckernel in "${boot_dir}/${GRUB_BTRFS_NKERNEL[@]}" ; do
[[ ! -f "${ckernel}" ]] && continue;
list_kernel+=("$ckernel")
done
fi
}
## Detect initramfs in "/boot"
detect_initramfs()
{
## Arch original initramfs (auto-detect)
for ainitramfs in "$(boot_dir)"/initramfs-* ; do
list_initramfs+=("$ainitramfs")
done
## Custom name initramfs in GRUB_BTRFS_NINIT
if [ ! -z "$ninit" ] ; then
for cinitramfs in "${ninit[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${cinitramfs}" ]] && continue;
list_initramfs+=("$cinitramfs")
done
fi
list_initramfs=()
# Original initramfs (auto-detect)
for oinitramfs in "${boot_dir}"/initrd.img-* \
"${boot_dir}"/initrd-*.img \
"${boot_dir}"/initrd-*.gz \
"${boot_dir}"/initramfs-*.img \
"${boot_dir}"/initramfs-*.gz ; do
[[ ! -f "${oinitramfs}" ]] && continue;
list_initramfs+=("$oinitramfs")
done
# Custom name initramfs in GRUB_BTRFS_NINIT
if [ ! -z "${GRUB_BTRFS_NINIT}" ] ; then
for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
[[ ! -f "${cinitramfs}" ]] && continue;
list_initramfs+=("$cinitramfs")
done
fi
}
## Detect microcode in "/boot"
detect_microcode()
{
## Arch original intel microcode
for aucode in "$(boot_dir)"/intel-ucode.img ; do
list_ucode+=("$aucode")
done
list_ucode=()
# Original intel/amd microcode (auto-detect)
# See "https://www.gnu.org/software/grub/manual/grub/html_node/Simple-configuration.html"
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
if [ ! -z "$microcode" ] ; then
for cucode in "${microcode[@]}" ; do
[[ ! -f /"$(boot_dir)"/"${cucode}" ]] && continue
list_ucode+=("$cucode")
done
fi
# Custom name microcode in GRUB_BTRFS_CUSTOM_MICROCODE
if [ ! -z "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
[[ ! -f "${cucode}" ]] && continue
list_ucode+=("$cucode")
done
fi
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
}
## Show full path snapshot or only name
path_snapshot()
{
case "${path_snapshot}" in
true) name_snapshot=("${snap_full_name}");;
*) name_snapshot=("${snap_full_name#*"/"}")
esac
case "${GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:-"true"}" in
true) name_snapshot=("${snap_full_name}");;
*) name_snapshot=("${snap_full_name#*"/"}")
esac
}
## Title format in grub-menu
title_format()
{
case "${title_format}" in
p/d/n) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}";;
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
p/d) title_menu="${prefixentry} ${snap_date_time}";;
p/n) title_menu="${prefixentry} ${name_snapshot}";;
d/n) title_menu="${snap_date_time} ${name_snapshot}";;
n/d) title_menu="${name_snapshot} ${snap_date_time}";;
p) title_menu="${prefixentry}";;
d) title_menu="${snap_date_time}";;
n) title_menu="${name_snapshot}";;
*) gettext_printf $"# Warning: GRUB_BTRFS_TITLE_FORMAT=${title_format}, syntax error \n" >&2
esac
case "${GRUB_BTRFS_TITLE_FORMAT:-"p/d/n"}" in
p/n/d) title_menu="${prefixentry} ${name_snapshot} ${snap_date_time}";;
p/d) title_menu="${prefixentry} ${snap_date_time}";;
p/n) title_menu="${prefixentry} ${name_snapshot}";;
d/n) title_menu="${snap_date_time} ${name_snapshot}";;
n/d) title_menu="${name_snapshot} ${snap_date_time}";;
p) title_menu="${prefixentry}";;
d) title_menu="${snap_date_time}";;
n) title_menu="${name_snapshot}";;
*) title_menu="${prefixentry} ${snap_date_time} ${name_snapshot}"
esac
}
## List of kernels, initramfs and microcode in snapshots
list_kernels_initramfs()
boot_bounded()
{
IFS=$'\n'
count_limit_snap=0
for item in $(snapshot_list); do
### fix: limit_snap_show=0
[[ ${limit_snap_show} -le 0 ]] && break;
IFS=$oldIFS
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
snap_dir_name="$(trim "$snap_dir_name")"
### ignore specific path during run "grub-mkconfig"
if [ ! -z "${ignore_specific_path}" ] ; then
for isp in ${ignore_specific_path[@]} ; do
[[ "${gbgmp}"/"${snap_dir_name}" == "${gbgmp}"/"${isp}"/* ]] && continue 2;
done
fi
### detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_dir_name/boot" ]] && continue;
### show snapshot found during run "grub-mkconfig"
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")"
if [[ "${show_snap_found}" = "true" ]]; then
gettext_printf $"# Found snapshot: %s\n" "$item" >&2 ;
fi
### Kernel (auto-detect + custom kernel)
unset list_kernel
detect_kernel
name_kernel=("${list_kernel[@]##*"/"}")
# echo "kernel = ${name_kernel[*]}"
if [[ "${harmonized_entries}" != "true" ]]; then
### Initramfs (autodetect + custom initramfs)
unset list_initramfs
detect_initramfs
name_initramfs=("${list_initramfs[@]##*"/"}")
# echo "initramfs = ${name_initramfs[*]}"
fi
### microcode (auto-detect + custom microcode)
unset list_ucode
detect_microcode
name_microcode=("${list_ucode[@]##*"/"}")
# echo "ucode = ${name_microcode[*]}"
### real path to boot
boot_dir_real_path="$(make_system_path_relative_to_its_root "$(boot_dir)")"
### 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
# Initialize menu entries
IFS=$'\n'
for item in $(snapshot_list); do
[[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
IFS=$oldIFS
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
snap_dir_name="$(trim "$snap_dir_name")"
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")"
boot_dir="$gbgmp/$snap_dir_name$boot_directory"
# Kernel (Original + custom kernel)
detect_kernel
if [ -z "${list_kernel}" ]; then continue; fi
name_kernel=("${list_kernel[@]##*"/"}")
# Detect rootflags
detect_rootflags
# Initramfs (Original + custom initramfs)
detect_initramfs
if [ -z "${list_initramfs}" ]; then continue; fi
name_initramfs=("${list_initramfs[@]##*"/"}")
# microcode (auto-detect + custom microcode)
detect_microcode
name_microcode=("${list_ucode[@]##*"/"}")
# 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
# convert /boot directory to root of GRUB (e.g /boot become /)
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")"
# Make menuentries
make_menu_entries
### Limit snapshots found during run "grub-mkconfig"
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
}
### 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 ###
gettext_printf "###### - Grub-btrfs: Auto-detect Start - ######\n" >&2 ;
### create mount point and mounts
[[ ! -d $gbgmp ]] && mkdir -p $gbgmp
mount -o subvolid=5 /dev/disk/by-uuid/$root_uuid $gbgmp/
### Create a menu in grub
echo "submenu '${submenuname}' {"
list_kernels_initramfs ;
## show total found snapshots
if [[ "${show_total_snap_found}" = "true" ]]; then
gettext_printf "# Found ${count_limit_snap} snapshot(s)\n" >&2 ;
fi
## if no snapshot found, show a warning
if [[ "${count_limit_snap}" = "0" ]]; then
echo " submenu '---> "No snapshot found : Press ESC to return previous menu" <---' { echo } ";
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 ;
fi
echo "}"
## unmount mount point
umount $gbgmp
gettext_printf "###### - Grub-btrfs: Auto-detect End - ######\n" >&2 ;
### End ###
# Kernel (Original + custom kernel)
detect_kernel
if [ -z "${list_kernel}" ]; then print_error "Kernels not found."; fi
name_kernel=("${list_kernel[@]##*"/"}")
# Initramfs (Original + custom initramfs)
detect_initramfs
if [ -z "${list_initramfs}" ]; then print_error "Initramfs not found."; fi
name_initramfs=("${list_initramfs[@]##*"/"}")
# microcode (auto-detect + custom microcode)
detect_microcode
name_microcode=("${list_ucode[@]##*"/"}")
# Initialize menu entries
IFS=$'\n'
for item in $(snapshot_list); do
[[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
IFS=$oldIFS
snap_full_name="$(echo "$item" | cut -d'|' -f2-)" # do not trim it to keep nice formatting
snap_dir_name="$(echo "$item" | cut -d'|' -f2)"
snap_dir_name="$(trim "$snap_dir_name")"
snap_date_time="$(echo "$item" | cut -d' ' -f1-2)"
snap_date_time="$(trim "$snap_date_time")"
# 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

63
Makefile Normal file
View File

@@ -0,0 +1,63 @@
PKGNAME ?= grub-btrfs
PREFIX ?= /usr
INITCPIO ?= false
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 test "$(INITCPIO)" = true; 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 test "$(INITCPIO)" != true && test -d "$(LIB_DIR)/initcpio"; 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 " parameter | type | description | defaults"
@echo " ----------+------+--------------------------------+----------------------------"
@echo " DESTDIR | path | install destination | <unset>"
@echo " PREFIX | path | system tree prefix | '/usr'"
@echo " SHARE_DIR | path | shared data location | '\$$(DESTDIR)\$$(PREFIX)/share'"
@echo " LIB_DIR | path | system libraries location | '\$$(DESTDIR)\$$(PREFIX)/lib'"
@echo " PKGNAME | name | name of the ditributed package | 'grub-btrfs'"
@echo " INITCPIO | bool | include mkinitcpio hook | false"
@echo

142
README.md
View File

@@ -1,97 +1,79 @@
[![GitHub release](https://img.shields.io/github/release/Antynea/grub-btrfs.svg)](https://github.com/Antynea/grub-btrfs)
### 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)
This is a version 1.xx of grub-btrfs
## grub-btrfs
#### Description
This is a version 4.xx of grub-btrfs
##### BTC donation address: `1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt`
##
### Description
Improves Grub by adding "btrfs snapshots" to the Grub menu.
grub-btrfs, Include btrfs snapshots at boot options. (grub menu)
You can start your system on a "snapshot" from the Grub menu.
Supports manual snapshots, snapper, timeshift ...
#### What does grub-btrfs v1.xx do :
##### Warning: booting on read-only snapshots can be tricky
Simple rollback using snapshots you made previously.
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).
##
### What does grub-btrfs v4.xx do :
* Automatically List snapshots existing on root partition (btrfs).
* Automatically Detect if "/boot" is in separate partition.
* Automatically Detect kernel, initramfs and intel/amd microcode in "/boot" directory on snapshots.
* Automatically Create corresponding "menuentry" in `grub.cfg`
* Automatically detect snapper and use snapper's snapshot description if available.
* Automatically generate `grub.cfg` if you use the provided systemd service.
* Automatically Detect kernel, initramfs and intel microcode in "/boot" directory on snapshots. (For custom name, see below.)
##
### Installation :
#### Arch Linux
* Automatically Create corresponding "menuentry" in grub.cfg , which ensures a very easy rollback.
```
pacman -S grub-btrfs
```
#### Manual
#### How to use it:
* Run `make install` or look into Makefile for instructions on where to put each file.
Add this lines to /etc/default/grub:
NOTE: Generate your Grub menu after installation for the changes to take effect.
On Arch Linux use `grub-mkconfig -o /boot/grub/grub.cfg`.
* GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots"
##
### Customization:
(Name menu appearing in grub.)
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_PREFIXENTRY="Snapshot:"
##
### 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.
(Add a name ahead your snapshots entries.)
* GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT="true"
(Show full path snapshot or only name)
* 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)
Generate grub.cfg (on Archlinux use grub-mkconfig -o /boot/grub/grub.cfg )
grub-btrfs automatically generates snapshots entries.
You will see it appear differents entries (e.g : Snapshot: [2014-02-12 11:24:37] my snapshot name overkill )
#### TO DO
* Snapper support
## discussion
Pour les francophones : https://forums.archlinux.fr/viewtopic.php?f=18&t=17177
Use `systemctl edit grub-btrfs.path`.
Then wrote:
```
[Path]
PathModified=/run/timeshift/backup/timeshift-btrfs/snapshots
```
and finally save.
* You can view your change to `systemctl cat grub-btrfs.path`.
* To revert change use `systemctl revert grub-btrfs.path`.
##### 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
* [maximbaz](https://github.com/maximbaz)
* [All contributors](https://github.com/Antynea/grub-btrfs/graphs/contributors)
##

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.