Compare commits

..

151 Commits

Author SHA1 Message Date
Jalopy
7e8a45ca9c Fix boot_uuid_subvolume fallback (#415)
Fix regression affecting systems where boot directory is not a Btrfs subvolume.
2026-02-19 09:21:08 +01:00
Jalopy
14fa71c994 add support for detached LUKS header and UUID fallbacks (#378)
Two hard failures prevented 41-snapshots-btrfs from generating a
snapshot submenu when the root LUKS header is detached and cryptdevice=
uses a /dev/disk/by-id path:

* grub-probe --target=fs_uuid aborted on detached headers.
* grep-based extraction of UUID from GRUB_CMDLINE_LINUX_DEFAULT failed
  when cryptdevice= did not contain “UUID=…”.

This patch:

1. Wraps grub-probe in a try/blkid/lsblk cascade that always returns the
   filesystem UUID or prints a clear error.
2. Replaces the fixed “cryptomount -u $(grep …UUID=…)” line with logic
   that:
   • accepts both UUID=… and /dev/disk/by-id/… syntaxes,
   • resolves paths to a canonical UUID with blkid,
   • emits ‘cryptomount -u <uuid>’ when possible,
   • falls back to ‘cryptomount -a’ only if no UUID can be extracted.
3. Keeps the previous behavior unchanged for unencrypted systems or for
   installations that already worked.

Result: snapshot menu is produced and boots correctly on standard
(setup with inline header), detached-header, and by-id configurations;
no regression for existing users.
2026-01-02 10:52:31 +01:00
Wayne Galen
2fcfbe9676 Ignore Podman container images (#380)
Same basic pattern as with Docker, but Podman uses a slightly different
path for this
2025-09-17 07:41:59 +02:00
TNE
9e171282da Get default early initrd list from GRUB_EARLY_INITRD_LINUX_STOCK (#389)
This mimics the behavior of grub more precisely

Fixes #388
2025-09-17 07:41:05 +02:00
cip91sk
b509fcaf61 add support for booting snapshots on LUKS encrypted disk (#333)
* add support for booting snapshots on LUKS encrypted disk

* documentation for booting from LUKS encrypted devices

* better detecting cryptdevice UUID
2025-01-06 08:11:45 +01:00
Pascal J
f682e17b30 Merge pull request #321 from StollD/set-subvolid
Add support for GRUB patches from SUSE
2024-04-08 17:02:40 +02:00
Pascal J
72a3dc092b Merge pull request #325 from aidan-gibson/master
Fix RAID
2024-03-27 18:16:20 +01:00
Aidan Gibson
6cb200a50b Fix RAID 2024-03-24 19:11:54 -07:00
Dorian Stoll
ece8d87151 Add support for GRUB patches from SUSE
Some GRUBs out there (Fedora, openSUSE) have an option that makes all
paths relative to the default subvolume of the filesystem. This can be
used to include /boot in your snapshots and roll them back without
having to regenerate grub.cfg.

However, enabling that option will break grub-btrfs, because loading the
kernel from a different snapshot requires the paths to be absolute.

To make this work, GRUB has to be told explicitly to access the root
subvolume when booting to a snapshot.
2024-03-10 12:56:37 +01:00
Pascal J
346a9868b8 Merge pull request #318 from expoodo/yabsnap_info_support
add support for yabsnap snapshot information
2024-03-06 14:48:24 +01:00
Pascal Jäger
b8465d14db fix spelling 2024-03-06 14:43:57 +01:00
Pascal J
0bc09317d8 Merge branch 'master' into yabsnap_info_support 2024-03-06 14:41:49 +01:00
Pascal J
94d742d1d4 Merge pull request #311 from bastien-roucaries/fix_bashism
Fix bashism
2024-03-06 14:24:44 +01:00
Pascal Jäger
363d7da3a7 fix typo uper -> upper 2024-03-06 14:23:26 +01:00
expoodo
585268dad7 Merge branch 'Antynea:master' into yabsnap_info_support 2024-02-19 15:18:18 -05:00
expoodo
34b54de71c removed redundant array slice 2024-02-19 15:16:26 -05:00
expoodo
a8713bbd0b mention yabsnap 2024-02-19 15:12:38 -05:00
Pascal Jäger
ac45f09af3 do not install compressed manpages
Fix #317

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2024-02-19 14:59:57 +01:00
expoodo
d41991979e add support for yabsnap snapshots info 2024-02-18 20:24:13 -05:00
Pascal J
99fc835e9c Merge pull request #305 from felixonmars/patch-1
Update Arch Linux package URL in README.md
2024-01-29 10:45:04 +01:00
Pascal J
5e608f8d96 Merge pull request #309 from yarikoptic/enh-codespell
Add codespell support (config, workflow to alert on new typos) + make it fix typos
2024-01-29 10:44:42 +01:00
Bastien Roucariès
465b56107f Add double quote if needed 2024-01-27 17:42:06 +00:00
Bastien Roucariès
7aa227b378 Fix 41_snapshots-btrs bashish [[ ]] 2024-01-27 17:38:55 +00:00
Yaroslav Halchenko
4ff82352bb Fix indentation after codespell 2023-12-21 19:25:54 -05:00
Yaroslav Halchenko
98a5bbe8c5 [DATALAD RUNCMD] run codespell throughout fixing typo automagically
=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^
2023-12-21 19:25:13 -05:00
Yaroslav Halchenko
abd2889464 [DATALAD RUNCMD] Do interactive fixing of some ambigous typos
=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w -i 3 -C 2 ./grub-btrfsd",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^
2023-12-21 19:25:10 -05:00
Yaroslav Halchenko
25a9876ad4 Add rudimentary codespell config 2023-12-21 19:24:42 -05:00
Yaroslav Halchenko
d82ee289c3 Add github action to codespell master on push and PRs 2023-12-21 19:24:13 -05:00
Felix Yan
ef150c17bb Update Arch Linux package URL in README.md
The old URL returns 404 now.
2023-11-21 16:42:56 +02:00
Brian Morison
490720a13c Update grub-btrfsd (#289)
fix grub.cfg path in grub submenu creation
2023-07-26 21:18:10 +02:00
Pascal J
ade5a91d55 fix #285 (#287) 2023-06-05 08:55:44 +02:00
Pascal Jäger
9a8a1b7d50 fix #278
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-28 18:26:25 +02:00
Pascal J
d51c96433c Remove openrc instructions for updating at system boot/ shutdown 2023-04-13 10:54:03 +02:00
Dan MacDonald
f461ea9cf1 More improvements to the README (#276)
* More improvements to the README

* Fix typo in README

* Adjust README according to Pascal's advice
2023-04-13 10:52:24 +02:00
Dan MacDonald
85571aab62 Correct first sentence of README 2023-04-11 08:52:34 +02:00
Dan MacDonald
2bbfddc46a Several edits and tweaks to the README 2023-04-11 08:52:34 +02:00
Pascal Jäger
3ce858f18d grub-btrfsd: refactor whole script
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-05 18:05:29 +02:00
Pascal Jäger
dd96f22888 grub-btrfsd: Check if all dirs exist
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-05 17:26:58 +02:00
Pascal Jäger
35429e02a4 grub-btrfsd: Kill process group on SIGTERM/ SIGINT
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-05 17:10:49 +02:00
Pascal Jäger
04958d6e0b grub-btrfsd: Start subdaemon when --timeshift-auto
Fix #272

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-05 17:09:30 +02:00
Pascal Jäger
c6550d0d96 grub-btrfs: unquote snap variable
Fix #273

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-04-05 13:40:40 +02:00
Pascal Jäger
c7d4bbbe45 Makefile: don't delete temp dir after installation
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 21:50:48 +02:00
Pascal Jäger
09a2a55ee4 Makefile: make docs installation optional
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 21:39:51 +02:00
Pascal Jäger
8105a2edf7 grub-btrfsd: watch more than one snapshot dir
Fix #262

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 21:08:16 +02:00
Pascal Jäger
879bec3697 grub-btrfsd: watch snapshots directory recursively
Fix: #262

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 20:44:50 +02:00
Pascal Jäger
e2937f6bff grub-btrfs: update comments
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 19:46:23 +02:00
Pascal Jäger
ec5ff8b4bc grub-btrfs: get back the grub_btrfs_search_directory functionality
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 19:46:05 +02:00
Pascal Jäger
1556c345da grub-btrfs: Do root fs detection with btrfs progs
Fix: #266 #255

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 19:44:56 +02:00
Pascal Jäger
8028a4376a grub-btrfsd: change condition to run script
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 18:56:35 +02:00
Pascal Jäger
0745117a76 Makefile: add variable GRUB_UPDATE_EXCLUDE
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
2032502e09 Makefile: add an if statement for RHEL distribs based 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
1d53472569 41_snapshots-btrfs: Create a bkp file. Delete the .new when no snapshots found. 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
8ea8046887 Update the Makefile 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
7586639f48 Auto execute the grub-mkconfig command at the installation 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
5ce2dfa640 Only recreation of the submenu 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
44c9cd16d0 Dynamic GRUB entry 2023-03-26 18:56:35 +02:00
Kevin Chevreuil - Kaisen
934a4a38e6 Force the deletion of the grub-btrfs.cfg file 2023-03-26 18:56:35 +02:00
Pascal J
87f030f6e8 Merge pull request #245 from Antynea/improve-config
Add kernel command line for snapshots as config parameter
2023-01-22 20:10:16 +01:00
Pascal J
1d33404c78 Merge branch 'master' into improve-config 2023-01-22 20:07:54 +01:00
Pascal Jäger
89ef805e81 grub-btrfsd: do no append with += to optional args
This does not work anymore, but it should be similar to the systemd
service file anyway, where things are just written in one line.

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-10 22:20:15 +01:00
Pascal Jäger
e03e87dd64 grub-btrfsd: Use bash as interpreter
Fix: #248

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-07 15:01:10 +01:00
Pascal Jäger
f131c38300 manpages: correct some minor things
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-06 23:10:24 +01:00
Pascal Jäger
934ab213b0 grub-btrfs: add custom kernel parameters option for snapshots
Fix #214, #160

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-06 22:56:44 +01:00
Pascal Jäger
f0ed56d242 grub-btrfs: Improve variable defaults
Fix #244

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-06 22:55:51 +01:00
Pascal Jäger
29ec43e9a6 grub-btrfsd: Fix non POSIX redirect
Squashed commit of the following:

commit d75feb59f4
Author: Pascal J <pascal.jaeger@leimstift.de>
Date:   Sun Dec 4 22:07:01 2022 +0100

    grub-btrsd: update shebang

commit a64379789c
Author: Pavin Joseph <pavinjosdev@gmail.com>
Date:   Sun Dec 4 22:52:31 2022 +0530

    Update grub-btrfsd

commit fe42568785
Author: Pavin Joseph <pavinjosdev@gmail.com>
Date:   Sun Dec 4 04:07:05 2022 +0530

    Update grub-btrfsd

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-12-04 22:11:00 +01:00
Kevin Chevreuil - Kaisen
6980771cd2 Don't display warnings when the mount command is used 2022-11-29 14:47:18 +01:00
Pascal Jäger
bc167ffe00 Readme: added instructions for --timeshift-old
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 17:59:38 +01:00
Pascal Jäger
b661e4e03f Merge branch 'fix-snap-dir-check' 2022-11-26 17:46:45 +01:00
Pascal Jäger
f594a56232 Merge branch 'improve-version-generation' 2022-11-26 17:44:06 +01:00
Pascal Jäger
fe48642596 Merge branch 'make-prefix-configurable' 2022-11-26 17:38:15 +01:00
Pascal Jäger
bfad9dcc1d grub-btrfs: Add possibility to configure where grub-btrfs.cfg is created and searched for
Closes #187

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 15:14:00 +01:00
Pascal Jäger
e3d0792a74 Post release version bump
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 15:10:28 +01:00
Pascal Jäger
efc4657aab grub-btrfsd: fixed message about flag dependencies
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 15:06:44 +01:00
Pascal Jäger
9e34f53ef8 Readme: discribe new version generation
Fix #237

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 15:03:10 +01:00
Pascal Jäger
6f154329c7 grub-btrfsd: fix if...else in daemon
add description of feature in manpage
fix non sh compatible commands in daemon

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-26 10:06:19 +01:00
Pascal Jäger
4942989d7f grub-btrfsd: add flag or old timeshift
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-25 16:58:07 +01:00
Pascal Jäger
91c4aac82c grub-btrfsd: make dir check of snapshots dir a warning
Bug #234

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-25 08:52:49 +01:00
Pascal Jäger
1d760ad730 Post release version bump
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-23 16:11:45 +01:00
Pascal Jäger
02c3fbb23a Version 4.12
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-23 15:58:11 +01:00
Pascal Jäger
13b6df8e9a grub-btrfsd: Add flag for colorless output
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-23 15:57:52 +01:00
Pascal Jäger
2186d831cd Readme, Manpages: Improve structure
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-23 15:57:10 +01:00
Pascal Jäger
c9620d5d18 grub-btrfs: Change syntax error message
I noticed that this is confusing in #230, user would search for errors in
the grub-btrfs.cfg file although the old grub-btrfs.cfg file is never
overwritten with grub-btrfs.new

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-21 22:59:22 +01:00
Pascal Jäger
33810a9274 grub-btrfs: print version of the script with --version
Close #225

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-21 22:59:22 +01:00
Pascal J
1969132073 Update README.md 2022-11-20 23:13:51 +01:00
Pascal Jäger
ead3849613 Readme: make instructions on how to run the script clearer
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-20 22:27:38 +01:00
Pascal Jäger
75f7d85261 grub-btrfs: Add warning when there is no entry in grub.cfg
Fix #219

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-20 22:15:48 +01:00
Pascal Jäger
d406ce795c grub-btrfsd: error when inotifywait is not found
Fix #227

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-20 21:34:40 +01:00
Pascal Jäger
b2b5307fe4 grub-btrfs: sanitize title menu entries
Closes #198

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-11-20 21:19:45 +01:00
Pascal Jaeger
57687ac0ab general: Update README, better instructions
for Fedora

Fix: #221

Signed-off-by: Pascal Jaeger <pascal.jaeger@leimstift.de>
2022-10-21 08:59:23 +02:00
Pascal J
a6e9caf6f4 Merge pull request #218 from Schievel1/update-daemon
Merge openRC and systemd daemon
2022-10-21 08:32:30 +02:00
Pascal J
36cee77bd8 Merge branch 'master' into update-daemon 2022-10-21 08:32:02 +02:00
Pascal Jäger
de68795d70 grub-btrfsd: better support commandline timeshift
When a snapshot is created with `timeshift --create` an the commandline,
sometimes the daemon is not fast enough between the
first (/run/timeshift) inotifywait and the second (an the actual
snapshot directory) inotifywait. Even without any `sleep` between them.
So now the grub (sub)menu is always created once in its own process when the daemon sees a
timeshift startup.

Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-10-21 08:27:51 +02:00
Pascal Jäger
4c63b65e9e grub-btrfsd: Error message when grub(-btrfs) fails
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-10-21 08:26:17 +02:00
Pascal J
bc09bbda65 Merge pull request #223 from S-trace/fix_silent_failure
Fix silent update-grub failure if root FS is not supported by GRUB2
2022-10-21 08:02:14 +02:00
Soul Trace
19f62ee6e6 Fix silent update-grub failure if root FS is not supported by GRUB2
If root FS is on volume not supported by GRUB2 - `update-grub` silently fails because `snapshots-btrfs` GRUB hook
silently fails at `root_fs=$(${grub_probe} --target="fs" /)` due to `set -e` at the beginning of `snapshots-btrfs`.

Failure of commands in test clause in Bash does not trigger set -v error and can be handled in script to
exit gracefully - implement this.

Fixes https://github.com/Antynea/grub-btrfs/issues/222
2022-10-18 17:52:25 +03:00
Pascal Jäger
4580c0fa2c grub-btrfsd: better instructions for daemon config
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-09-05 20:20:47 +02:00
Pascal J
44573e5282 grub-btrfsd: Change the LogLevel
Against spamming the syslog
2022-09-03 08:31:25 +02:00
Pascal Jäger
5805029c79 grub-btrfsd: fix problem missing /run/timeshift
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-09-02 22:58:37 +02:00
Pascal Jäger
9064d61145 grub-btrfsd: add verbose and syslog options
Signed-off-by: Pascal Jäger <pascal.jaeger@leimstift.de>
2022-09-02 22:58:37 +02:00
Pascal J
8c8ee200fd general: Formatted Readme a bit 2022-09-02 22:58:31 +02:00
Pascal Jäger
961675ca31 grub-btrfsd: Merge openrc and systemd daemon
Fix #213, Fix #211, Fix #215
2022-09-02 22:57:34 +02:00
Pascal J
14c42b82eb grub-btrfsd: Update README.md, Fix #213
Signed-off-by: Jaeger <Pascal.Jaeger@bode-kassel.com>
2022-09-02 22:57:24 +02:00
Pascal Jäger
6280f95139 grub-btrfs: Give messages when the script exits 2022-09-02 22:57:00 +02:00
Pascal Jäger
d54f3d7366 grub-btrfsd: Fix #211 for OpenRC-Daemon 2022-09-02 22:56:44 +02:00
Pascal J
c78bd25784 Merge pull request #210 from Megver83/openrc
OpenRC scripts: add configuration file
2022-09-02 09:25:07 +02:00
David P
0182e11951 OpenRC scripts: add configuration file
This allows users to customize the snapshots path to work with, e.g., snapper.
If no path is configured, it will default to timeshift.

Signed-off-by: David P <megver83@parabola.nu>
2022-06-26 19:32:11 -04:00
Re4son Kernel
3dc1d89965 Add Kali Linux to README (#201)
Kali Linux added grub-btrfs to its repository. This commit reflects that.
2022-02-16 04:15:44 +01:00
Semnodime
fc4a5a8e56 Update README.md (#197)
Reformat, beautify and clarify the README.md and promote consistent wording.
The install section regarding timeshift has changed the most.
2022-01-28 05:27:01 +01:00
budswa
a146cd5c9d Fixed grammatical mistake in the output (#194) 2022-01-20 19:04:05 +01:00
budswa
8dbe80c0bd Fixed output to be gramatically correct (#193) 2022-01-07 12:09:18 +01:00
Antynea
79ae25ea5d Update installation section
Adds make help
2021-11-29 18:58:09 +01:00
Antynea
ee3c366fa4 Add missing initrd (#184) 2021-11-26 02:49:37 +01:00
Antynea
4f1aa38604 Make path of "grub-mkconfig_lib" configurable (#181)
* Make path of "grub-mkconfig_lib" configurable

  * 41_snapshots-btrfs file:
    - Remove "datarootdir" variable, is no longer used
    - Replace "$datarootdir/grub/grub-mkconfig_lib" with "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}"

  * Config file:
    - Adds new GRUB_BTRFS_MKCONFIG_LIB variable
Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (Opensuse ...)
2021-11-17 19:30:34 +01:00
Antynea
1accd5e272 Make name of "grub-script-check" configurable (#177)
41_snapshots-btrfs file:
  * Remove "grub_script_check" variable

Config file;
  * Make name of "grub-script-check" configurable
    * Might be 'grub2-script-check' on some systems (Fedora ...)
2021-11-07 14:35:17 +01:00
Antynea
2500ce8d30 Fix broken Makefile:
* Remove empty lines.
  * Adds missing double quote.
  * Deleted files differ from installed files:
    * Installed files:
      - "$(BIN_DIR)/" grub-btrfs-openrc;
      - "$(DESTDIR)/etc/init.d/" grub-btrfsd;

    * Deleted files:
      - "$(BIN_DIR)/grub-btrfs.openrcbin";
      - "$(DESTDIR)/etc/init.d/grub-btrfs.openrc";

    * Replace deleted files with:
      - "$(BIN_DIR)/grub-btrfs-openrc;"
      - "$(DESTDIR)/etc/init.d/grub-btrfsd;"
2021-11-07 13:55:18 +01:00
Antynea
d9f54afcb7 Update Installation section:
Update Dependencies
2021-11-04 12:26:23 +01:00
Antynea
33ad3273d3 * trim trailing whitespace.
* snapshot_list function:
  * Rename some variables for better consistency.
  * Remove unused variables.
  * Ignore snapper/timeshift snapshot as soon as possible.
2021-11-02 17:42:28 +01:00
Pascal Jäger
3b0d0c4ff7 changed makefile so it doesnt intefere with arch package build process 2021-11-02 16:18:04 +01:00
Pascal Jäger
66a218356a changed instruction for openrc local service 2021-11-02 16:18:04 +01:00
Pascal Jäger
7dc240faa7 Updated readme to take openRC daemon into consideration 2021-11-02 16:18:04 +01:00
Pascal Jäger
75e6408510 Added openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
fbc33391cb Added openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
63c3493504 Added a openRC daemon 2021-11-02 16:18:04 +01:00
Pascal Jäger
02b925e4b5 Added an openRC daemon 2021-11-02 16:18:04 +01:00
Antynea
9d436adf95 Reworks many things (#174)
#### Script:
* Snapper:
  - Now, the information is retrieved from the info.xml file.

* Timeshift:
  * Now, the information is retrieved from the info.json file.

* Probe informations from device:
  * Add the UUID of the root and boot subvolumes

* Show full path snapshot or only name:
  * Remove, this feature never worked correctly

* Grub-menu:
  * Now displays the following information in separate columns:
    - Date of snapshot
    - Path of snapshot
    - Type/Tags of snapshot if available (snapper/timeshift)
    - Description/Comments of snapshot if available (snapper/timeshift)
  * Possibility to display only the desired information(s) (see config file)
  *  Adds a header for the column title
  * GRUB_BTRFS_PREFIXENTRY is remove

  * Boot partition detection:
    * grub-btrfs is now able to detect if the boot folder/partition is a subvolume
    * GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION should no longer be needed for this case

  * Variables:
    * Rename some variables

  * Header:
    * Update the header to reflect the changes.

#### Config:
* GRUB_BTRFS_PREFIXENTRY:
  * Remove, no longer use

* GRUB_BTRFS_DISPLAY_PATH_SNAPSHOT:
  * Remove, no longer use

* GRUB_BTRFS_TITLE_FORMAT:
  * Shows/Hides "date" "snapshot" "type" "description" in the Grub menu, custom order available.
    Default: ("date" "snapshot" "type" "description")

* GRUB_BTRFS_IGNORE_SNAPPER_TYPE:
  * Rename to GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE
    - Supports both timeshift and snapper tags/type

* GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION:
  * Rename to GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION
    - Supports both snapper and timeshift description/comments

* GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION:
  * grub-btrfs is now able to detect if the boot folder/partition is a subvolume.
  Activating this parameter should no longer be necessary for this case.

* GRUB_BTRFS_SNAPPER_CONFIG:
  * Remove, no longer use

#### Readme:
* Update "What does grub-btrfs v4.xx do" section
  * Adds support for timeshift
2021-10-25 15:47:26 +02:00
Antynea
301752f300 Update count_limit_snap arithmetic
* Update count_limit_snap arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:59:08 +02:00
Antynea
3b857348cb Update wait_max arithmetic
* Update wait_max arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:54:11 +02:00
Antynea
f3d8e99cb8 Update count_warning_menuentries arithmetic
* Update count_warning_menuentries arithmetic:
  * "$" isn't required in an arithmetic function
2021-10-21 16:50:51 +02:00
Antynea
af80fe7993 Comments unused variables
* Comments unused variables:
  * This "$prefix_i" and "$suffix_i" are for information purposes only, and aren't used.
2021-10-21 16:44:59 +02:00
Antynea
c7f403d2a2 Update "GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU"
* Update "GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU":
  * Remove default parameter (false), not needed
  * adds automatic conversion of the value to lower case
2021-10-21 16:39:17 +02:00
Antynea
e6898c0de8 Update disable_script function
* Update disable_script function:
  * A function is no longer required since the commands have been moved to the beginning of the script.
2021-10-21 16:36:12 +02:00
Antynea
a790ff054e "disable_script" function breaks "grub-mkconfig"
* "disable_script" function breaks "grub-mkconfig":
  * Replace "return 1" by "exit 0".
2021-10-07 17:31:45 +02:00
Antynea
df643361cc Add Gentoo and OpenRC instructions
* Add Gentoo instructions in "Installation :" section.
* Add OpenRC instructions in "Automatically update grub :" section
2021-10-07 16:52:44 +02:00
Antynea
b0408225c1 Fix bug Create entries with matching version (#170)
* Fix #169 
  * Create entries with matching version doesn't work properly:
  Adds missing "else continue;"
2021-09-26 19:05:02 +02:00
Antynea
8142691be1 Adds missing newline
* Adds missing newline:
  "\n" was missing.
2021-09-24 15:54:04 +02:00
Antynea
bab78d4ed8 Write-protect user data
* Write-protect user data
  * The script does not need write access to the data.
  Adds "ro" flags to provide protection against accidental writing.
2021-09-24 12:24:15 +02:00
Antynea
544d2e84ac Adds security if a false positive is detected
* Adds security if a false positive is detected:
  * if the command "grep -qs "$gbgmp" /proc/mounts;" returns a false positive.
  "rm -d" will return an error if the directory is not empty.
2021-09-24 12:12:43 +02:00
Antynea
b346727219 Deletes unused code
* Deletes unused code:
  * Limit generation of menuentries if exceeds 250 has never been used.
  Uses "GRUB_BTRFS_LIMIT" (default 50) instead
2021-09-23 15:28:28 +02:00
Antynea
f1ca0db36d Update header installation section
* Update header installation section:
  * Remove instructions
  (Refet to the project website, installation section)
2021-09-23 14:54:59 +02:00
Antynea
c4d0df3a97 Rework the creation of the "grub-btrfs.cfg" file.
* Rework the creation of the "grub-btrfs.cfg" file:
  * Before, the "grub-btrfs.cfg" file was deleted and then the new configuration was written.
  No backup was made.
  * Now, the new configuration will be written in a temporary file "grub-btrfs.new" and then analysed with the "grub_script_check" command before being finally written in the "grub-btrfs.cfg" file.
  If an error is detected, the "grub-btrfs.new" file will coexist with the old "grub-btrfs.cfg" file, if it exists.
2021-09-23 14:49:56 +02:00
Antynea
c1cadccd1f Adds trap command on EXIT signal
* Adds trap command on EXIT signal:
  * Now umount command will launch on EXIT signal. 
  * Adds a function called by the trap on EXIT signal to unmount and delete the temporary folder. 
  (That should be the end of multiple tmp.xxxxxxxxxx in /tmp)
    - If the command fails, retry every 2 seconds. After 10 attempts, it will stop and display a warning.
    - If the command is successful, "Succes" will be displayed.
  * Adds "grub-btrfs" as a prefix to the temporarie mount folder.
  (before = tmp.xxxxxxxxx , now = grub-btrfs.xxxxxxxxxx)
2021-09-23 11:49:21 +02:00
Antynea
8cc214fd0e Corrects printf format string
* Corrects printf format string:
  * printf interprets escape sequences and format specifiers in the format string. If variables are included, any escape sequences or format specifiers in the data will be interpreted too, when you most likely wanted to treat it as data.
2021-09-22 19:08:55 +02:00
Antynea
81bde02b03 Update "Installation section"
* Update "Installation section":
  * Adds required dependencies
  * Indicates that the command "update-grub", is an alias to "grub-mkconfig" on Debian-like distributions.
2021-09-22 17:07:44 +02:00
Antynea
14bf041ba6 Deactivate the script as soon as possible
* With these changes, the script will be disabled as soon as possible, if :
  * "GRUB_BTRFS_DISABLE" If this variable is set to "true"
  * "btrfs-progs isn't installed" This package is required to retrieve information from the btrfs filesystem.
  * "grub-mkconfig_lib couldn't be found" This library is required because the script depends on it.
  * "Root filesystem isn't btrfs" grub-btrfs currently checks only the btrfs snapshots present on the root partition.
2021-09-22 15:49:02 +02:00
Antynea
863107588c Remove redundant check
Running a command and then checking its exit status $? against 0 is redundant.
Instead of just checking the exit code of a command, it checks the exit code of a command that checks the exit code of a command.
2021-09-22 15:40:05 +02:00
Antynea
2851ecd72b Removes double negation in file test operators
* Removes double negation in file test operators:
  * Replaces the "! -z" operator with "-n".
2021-09-22 15:31:03 +02:00
Antynea
679d000446 Add possibility to boot without init (#164)
* Add possibility to boot without init(rd,ramfs):
  - For a snapshot to be valid, it must contain a boot folder and a kernel from the official list (or have been added to the custom kernel list)
  - if a snapshot doesn't contain an init(rd,ramfs), it will be detected as valid.
  - Suppress script stop when an init is not found
  - If init isn't found, add the letter "x" to the init list. (hoping this doesn't break the support for custom init names)
  - The microcode support is still present, despite the absence of init(rd,ramfs), is it really relevant ?
2021-09-17 15:39:23 +02:00
Antynea
981777d745 Add filter snapper's snapshot (#158)
- Add filter to ignore snapper's snapshot "type or description" during run "grub-mkconfig"

- Two new variables available in the config file:
# Ignore specific type of snapper's snapshot during run "grub-mkconfig".
# Type = single, pre or post.
# Default: ("")
GRUB_BTRFS_IGNORE_SNAPPER_TYPE=("")

# Ignore specific description of snapper's snapshot during run "grub-mkconfig".
# Default: ("")
GRUB_BTRFS_IGNORE_SNAPPER_DESCRIPTION=("")
2021-07-14 12:48:20 +02:00
Björn Daase
3433754c69 Makefile: Make sure make is invoked with appropriate permissions (#146) 2021-03-01 13:35:44 +01:00
Antynea
db753a9ac8 41_snapshots: update header
* 41_snapshots: update header
  * Update "Automatically update Grub" section.
  * Update "Purpose" section.
  * Update "What this script does" section
2021-02-21 15:37:43 +01:00
Antynea
83bf1da01e Improves systemd.path unit (#139)
* grub-btrfs.path : improves unit

#### Remember to modify your configuration accordingly.  
Allows the unit to start and stop automatically when the mount point is detected.  
If the mount point is already mounted when the unit is activated `systemctl enable grub-btrfs.path`,  
it will be necessary to start the unit for monitoring to begin `systemctl start grub-btrfs.path`.

- `DefaultDependencies=no`
Prevents systemd from automatically generating `Wants= or Requires= or After=`.
- `Requires=\x2esnapshots.mount`
Ensures unit is started if mount point exists.
- `After=\x2esnapshots.mount`
Unit start after the mounting point exists.
- `BindsTo=\x2esnapshots.mount`
If the mount point is removed, the unit will stop.
- `PathModified=\x2esnapshots.mount`
The monitored folder containing the snapshots.
- `WantedBy=\x2esnapshots.mount`
If the mount point exists, unit start automatically. (only if unit is activated before the mount point is mounted)

* Readme: Update "Automatically update grub" section

Update section following the recent change in the `grub-btrfs.path` unit.  
Add information to be able to update the `grub-btrfs` menu every time the system is restart/shutdown.
2021-02-21 05:26:39 +01:00
19 changed files with 2389 additions and 425 deletions

6
.codespellrc Normal file
View File

@@ -0,0 +1,6 @@
[codespell]
skip = .git,*.pdf,*.svg,go.sum,.codespellrc
check-hidden = true
# ignore-regex =
# ist -- unfortunate variable
ignore-words-list = ist

22
.github/workflows/codespell.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
---
name: Codespell
on:
push:
branches: [master]
pull_request:
branches: [master]
permissions:
contents: read
jobs:
codespell:
name: Check for spelling errors
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Codespell
uses: codespell-project/actions-codespell@v2

View File

@@ -1,38 +1,35 @@
#! /usr/bin/env bash
#
#
# 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
# You can boot your system on a "snapshot" from the Grub menu.
# Supports manual snapshots, snapper, timeshift ...
# 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 Detect kernel, initramfs and intel/amd microcode in "/boot" directory on snapshots.
# - Automatically Create corresponding "menuentry" in grub.cfg.
# - Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
# - 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.
# - Refer to https://github.com/Antynea/grub-btrfs#%EF%B8%8F-installation
#
# Customization:
# Refer to config for the list of available options and their default values.
# Place your configurations to /etc/default/grub-btrfs/config.
# You have the possibility to modify many parameters in /etc/default/grub-btrfs/config.
# Read more here https://github.com/Antynea/grub-btrfs#installation- an in the manpage
# 'man grub-btrfs'
#
# 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
# If you would like grub-btrfs menu to automatically update when a snapshot is created or deleted:
# - Refer to https://github.com/Antynea/grub-btrfs#-automatically-update-grub-upon-snapshot.
#
# Special thanks for assistance and contributions:
# - My friends
@@ -41,73 +38,166 @@
set -e
prefix="/usr"
exec_prefix="/usr"
datarootdir="/usr/share"
sysconfdir="/etc"
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
[[ -f "$grub_btrfs_config" ]] && . "$grub_btrfs_config"
. "$datarootdir/grub/grub-mkconfig_lib"
. "${sysconfdir}/default/grub"
[ -f "$grub_btrfs_config" ] && . "$grub_btrfs_config"
[ -f "${sysconfdir}/default/grub" ] && . "${sysconfdir}/default/grub"
## Error Handling
print_error()
{
local err_msg="$*"
local bug_report="If you think an error has occurred, please file a bug report at \"https://github.com/Antynea/grub-btrfs\""
printf "%s\n" "${err_msg}" "${bug_report}" >&2 ;
exit 0
}
# parse arguments
while getopts :V-: opt; do
case "$opt" in
-)
case "${OPTARG}" in
version)
printf "Version %s\n" "${GRUB_BTRFS_VERSION}" >&2 ;
exit 0
;;
esac;;
V)
printf "Version %s\n" "${GRUB_BTRFS_VERSION}" >&2 ;
exit 0
;;
*)
printf "Unknown flag, exiting...\n"
exit 0
;;
esac
done
## Exit the script, if:
[ "$(echo "$GRUB_BTRFS_DISABLE" | tr '[:upper:]' '[:lower:]')" = 'true' ] && print_error "GRUB_BTRFS_DISABLE is set to true (default=false)"
if ! type btrfs >/dev/null 2>&1; then print_error "btrfs-progs isn't installed"; fi
[ -f "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" ] && . "${GRUB_BTRFS_MKCONFIG_LIB:-/usr/share/grub/grub-mkconfig_lib}" || print_error "grub-mkconfig_lib couldn't be found"
[[ "$(btrfs filesystem df / 2>&1)" == *"not a btrfs filesystem"* ]] && print_error "Root filesystem isn't btrfs"
printf "Detecting snapshots ...\n" >&2 ;
### Variables in /etc/default/grub-btrfs/config
## Disable Grub-btrfs (default=active)
[[ "${GRUB_BTRFS_DISABLE:-"false"}" == "true" ]] && exit 0
## Submenu name
distro=$(awk -F "=" '/^NAME=/ {gsub(/"/, "", $2); print $2}' /etc/os-release)
distro=$(awk -F "=" '/^NAME=/ {gsub(/"/, "", $2); print $2}' /etc/os-release) # escape '
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"${distro:-Linux} snapshots"}
## Prefix entry
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot:"}
## Limit snapshots to show in the Grub menu
## Limit snapshots to show in the Grub menu (default=50)
limit_snap_show="${GRUB_BTRFS_LIMIT:-50}"
## How to sort snapshots list
btrfssubvolsort=(--sort="${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}")
## Snapper's config name
snapper_config=${GRUB_BTRFS_SNAPPER_CONFIG:-"root"}
btrfs_subvolume_sort="--sort=${GRUB_BTRFS_SUBVOLUME_SORT:-"-rootid"}"
## 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"}
## Customize GRUB-BTRFS.cfg directory, where "grub-btrfs.cfg" file is saved
grub_btrfs_directory=${GRUB_BTRFS_GBTRFS_DIRNAME:-${grub_directory}}
## Customize directory where "grub-btrfs.cfg" file is searched for by grub
grub_btrfs_search_directory=${GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME:-"\${prefix}"}
## Password protection management for submenu
# Protection support for submenu (--unrestricted)
case "${GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU:-"false"}" in
case "$(echo "$GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU" | tr '[:upper:]' '[:lower:]')" in
true) unrestricted_access_submenu="--unrestricted ";;
*) unrestricted_access_submenu=""
esac
# Authorized users (--users foo,bar)
if [ ! -z "${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS}" ] ; then
if [ -n "${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS}" ] ; then
protection_authorized_users="--users ${GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS} "
fi
## Probe information of Root and Boot devices
# -----------------------------------------------------------
# ---------- Root partition ----------
root_device="$(${grub_probe} --target=device /)" # e.g. /dev/mapper/enc
root_uuid="$(${grub_probe} --device "${root_device}" --target=fs_uuid 2>/dev/null)" || true
# Fallback when grub-probe fails (encrypted container, detached header…)
if [ -z "$root_uuid" ]; then
root_uuid="$(blkid -s UUID -o value "${root_device}" 2>/dev/null)"
fi
[ -z "$root_uuid" ] && print_error "Cannot determine UUID of ${root_device}"
# Root subvolume UUID
root_uuid_subvolume="$(btrfs subvolume show / 2>/dev/null | \
awk -F':' '/^\s*UUID/ {gsub(/^[ \t]+/, "", $2); print $2}')"
[ -z "$root_uuid_subvolume" ] && print_error "UUID of the root subvolume is not available"
# ---------- Boot partition ----------
boot_device="$(${grub_probe} --target=device "${boot_directory}")" # e.g. /dev/sdb1
boot_uuid="$(${grub_probe} --device "${boot_device}" --target=fs_uuid 2>/dev/null)" || true
# Fallback for boot UUID
if [ -z "$boot_uuid" ]; then
boot_uuid="$(blkid -s UUID -o value "${boot_device}" 2>/dev/null)"
fi
[ -z "$boot_uuid" ] && print_error "Cannot determine UUID of ${boot_device}"
# If /boot is not a Btrfs subvolume, reuse root subvol UUID
boot_uuid_subvolume="$(
btrfs subvolume show "${boot_directory}" 2>/dev/null | \
awk -F':' '/^\s*UUID/ {gsub(/^[ \t]+/, "", $2); print $2; exit}'
)"
[ -z "$boot_uuid_subvolume" ] && boot_uuid_subvolume="$root_uuid_subvolume"
# Extra data for GRUB commands
boot_hs="$(${grub_probe} --device "${boot_device}" --target=hints_string 2>/dev/null)"
boot_fs="$(${grub_probe} --device "${boot_device}" --target=fs 2>/dev/null)"
# -----------------------------------------------------------
## Enable LUKS encrypted devices support
case "$(echo "$GRUB_BTRFS_ENABLE_CRYPTODISK" | tr '[:upper:]' '[:lower:]')" in
true)
list_insmods=(
"insmod gzio"
"insmod part_gpt"
"insmod cryptodisk"
"insmod luks"
"insmod gcry_rijndael"
"insmod gcry_rijndael"
"insmod gcry_sha256"
"insmod ${boot_fs}"
)
# Extract the <source> field of cryptdevice=<source>:<name>[:header]
crypt_source="$(printf '%s %s\n' "$GRUB_CMDLINE_LINUX_DEFAULT" "$GRUB_CMDLINE_LINUX" \
| grep -o -P 'cryptdevice=\K[^:]+' || true)"
# Turn the source into a UUID that cryptomount -u understands
crypt_uuid=""
if [[ "$crypt_source" =~ ^UUID=.* ]]; then # already UUID=…
crypt_uuid="${crypt_source#UUID=}"
elif [[ "$crypt_source" == /dev/* ]]; then # path → resolve → blkid
real_dev=$(readlink -f "$crypt_source" 2>/dev/null || true)
[ -b "$real_dev" ] && crypt_uuid=$(blkid -s UUID -o value "$real_dev" 2>/dev/null || true)
fi
# Emit the proper cryptomount command
if [[ "$crypt_uuid" =~ ^[0-9a-fA-F-]{36}$ ]]; then
list_insmods+=("cryptomount -u ${crypt_uuid}")
else
# last-resort: scan all crypto containers (works but a bit slower)
list_insmods+=("cryptomount -a")
fi
;;
*)
list_insmods=("insmod ${boot_fs}")
;;
esac
### 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"
kernel_parameters="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT $GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS"
## Mount point location
gbgmp=$(mktemp -d)
grub_btrfs_mount_point=$(mktemp -dt grub-btrfs.XXXXXXXXXX)
## Class for theme
CLASS="--class snapshots --class gnu-linux --class gnu --class os"
## save IFS
oldIFS=$IFS
## Detect uuid requirement (lvm,btrfs...)
check_uuid_required() {
if [ "x${root_uuid}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
if [ "${root_uuid}" = "" ] || [ "${GRUB_DISABLE_LINUX_UUID}" = "true" ] \
|| ! test -e "/dev/disk/by-uuid/${root_uuid}" \
|| ( test -e "${root_device}" && uses_abstraction "${root_device}" lvm ); then
LINUX_ROOT_DEVICE=${root_device}
@@ -118,66 +208,122 @@ fi
## Detect rootflags
detect_rootflags()
{
local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${gbgmp}/${snap_dir_name}/etc/fstab" \
local fstabflags=$(grep -oE '^\s*[^#][[:graph:]]+\s+/\s+btrfs\s+[[:graph:]]+' "${grub_btrfs_mount_point}/${snap_dir_name_trim}/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()
unmount_grub_btrfs_mount_point()
{
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()
{
[[ "$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."
if [ -d "$grub_btrfs_mount_point" ]; then
local wait=true
local wait_max=0
printf "Unmount %s .." "$grub_btrfs_mount_point" >&2;
while $wait; do
if grep -qs "$grub_btrfs_mount_point" /proc/mounts; then
wait_max=$((1+wait_max))
if umount "$grub_btrfs_mount_point" >/dev/null 2>&1; then
wait=false # umount successful
printf " Success\n" >&2;
elif [ $wait_max -eq 10 ]; then
printf "\nWarning: Unable to unmount %s in %s\n" "$root_device" "$grub_btrfs_mount_point" >&2;
break;
else
printf "." >&2 ; # output to show that the script is alive
sleep 2 # wait 2 seconds before retry
fi
else
wait=false # not mounted
printf " Success\n" >&2;
fi
done
if [ "$wait" != true ]; then
if ! rm -d "$grub_btrfs_mount_point" >/dev/null 2>&1; then
printf "Unable to delete %s: Device or resource is busy\n" "$grub_btrfs_mount_point" >&2;
fi
fi
set -e
fi
}
### Script
## Create entry
entry()
{
echo "$@" >> "$grub_directory/grub-btrfs.cfg"
echo "$@" >> "$grub_btrfs_directory/grub-btrfs.new"
}
## menu entries
make_menu_entries()
{
## \" required for snap,kernels,init,microcode with space in their name
entry "submenu '$title_menu' {
submenu '---> $title_menu <---' { echo }"
entry "submenu '${title_menu}' {
submenu '${title_submenu}' { echo }"
for k in "${name_kernel[@]}"; do
[[ ! -f "${boot_dir}"/"${k}" ]] && continue;
[ ! -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' {"
if [ "${name_initramfs}" != "x" ] ; then
# 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
entry "\
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"
for j in "${insmods[@]}"; do
entry "\
${j}"
done
entry "\
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"
if [ "${SUSE_BTRFS_SNAPSHOT_BOOTING:-"false"}" = "true" ]; then
entry "\
set btrfs_subvolid=5"
fi
entry "\
echo 'Loading Snapshot: "${snap_date_trim}" "${snap_dir_name_trim}"'
echo 'Loading Kernel: "${k}" ...'
linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name_trim}"\""
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
else
for u in "${name_microcode[@]}"; do
if [ "${name_microcode}" != "x" ] ; then
entry "
menuentry ' "${k}" & "${u}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
else
entry "
menuentry ' "${k}"' ${CLASS} "\$menuentry_id_option" 'gnulinux-snapshots-$boot_uuid' {"
fi
entry "\
if [ x\$feature_all_video_module = xy ]; then
insmod all_video
fi
@@ -187,22 +333,24 @@ make_menu_entries()
search --no-floppy --fs-uuid --set=root ${boot_hs} ${boot_uuid}
else
search --no-floppy --fs-uuid --set=root ${boot_uuid}
fi"
if [ "${SUSE_BTRFS_SNAPSHOT_BOOTING:-"false"}" = "true" ]; then
entry "\
set btrfs_subvolid=5"
fi
echo 'Loading Snapshot: "${snap_date_time}" "${snap_dir_name}"'
entry "\
echo 'Loading Snapshot: "${snap_date_trim}" "${snap_dir_name_trim}"'
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
linux \"${boot_dir_root_grub}/"${k}"\" root="${LINUX_ROOT_DEVICE}" ${kernel_parameters} ${rootflags}subvol=\""${snap_dir_name_trim}"\""
if [ "${name_microcode}" != "x" ] ; then
entry "\
echo 'Loading Microcode: "${u}" ...'
initrd \"${boot_dir_root_grub}/"${u}"\""
fi
entry " }"
count_warning_menuentries=$((1+count_warning_menuentries))
done
fi
done
done
entry "}"
@@ -219,98 +367,125 @@ trim() {
## 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
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 --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
local snapper_info="info.xml"
local timeshift_info="info.json"
local date_snapshots=()
local path_snapshots=()
local type_snapshots=()
local description_snapshots=()
IFS=$'\n'
# Parse btrfs snapshots
local entries=()
local ids=()
local max_entry_length=0
for snap in $(btrfs subvolume list -sa "${btrfssubvolsort}" /); do
for snap in $(btrfs subvolume list -sa "${btrfs_subvolume_sort}" /); do # Parse btrfs snapshots
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#*"/"}
snap=(${snap})
local path_snapshot=${snap[@]:13:${#snap[@]}}
if [ "$path_snapshot" = "DELETED" ]; then continue; fi # Discard deleted snapshots
[[ ${path_snapshot%%"/"*} == "<FS_TREE>" ]] && path_snapshot=${path_snapshot#*"/"} # Remove the "<FS_TREE>" string at the beginning of the path
# 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;
if [ -n "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH}" ] ; then
for isp in "${GRUB_BTRFS_IGNORE_SPECIFIC_PATH[@]}" ; do
[ "${path_snapshot}" = "${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;
if [ -n "${GRUB_BTRFS_IGNORE_PREFIX_PATH}" ] ; then
for isp in "${GRUB_BTRFS_IGNORE_PREFIX_PATH[@]}" ; do
[[ "${path_snapshot}" == "${isp}"/* ]] && continue 2;
done
fi
[ ! -d "$grub_btrfs_mount_point/$path_snapshot/boot" ] && continue; # Discard snapshots without /boot folder
# Parse Snapper & timeshift & yabsnap information
local type_snapshot="N/A"
local description_snapshot="N/A"
# path to yabsnap snapshot meta data
local yabsnap_info="$grub_btrfs_mount_point/${path_snapshot%"/"*}/$(echo "${snap[13]}" | awk -F'/' '{print $3 "-meta.json"}')"
if [[ -s "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info" ]] ; then
type_snapshot=$(awk -F"<|>" 'match($2, /^type/) {print $3}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info") # search matching string beginning "type"
description_snapshot=$(awk -F"<|>" 'match($2, /^description/) {print $3}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$snapper_info") # search matching string beginning "description"
elif [[ -s "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info" ]] ; then
type_snapshot=$(awk -F" : " 'match($1, /^[ \t]+"tags"/) {gsub(/"|,/,"");print $2}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info") # search matching string beginning "tags"
description_snapshot=$(awk -F" : " 'match($1, /^[ \t]+"comments"/) {gsub(/"|,/,"");print $2}' "$grub_btrfs_mount_point/${path_snapshot%"/"*}/$timeshift_info") # search matching string beginning "comments" fix '
elif [[ -s $yabsnap_info ]] ; then
type_snapshot=$(grep -P '^\s*"trigger"' $yabsnap_info | awk -F'"' '{print $4}') # search matching string beginning "trigger"
description_snapshot=$(grep -P '^\s*"comment"' $yabsnap_info | awk -F'"' '{print $4}') # search matching string beginning "comment"
fi
[ -z "$type_snapshot" ] && type_snapshot=("N/A")
[ -z "$description_snapshot" ] && description_snapshot=("N/A")
# ignore specific {type,tag,description} of snapshot during run "grub-mkconfig"
if [ -n "${GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE}" ] ; then
for ist in "${GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE[@]}" ; do
[ "${type_snapshot}" = "${ist}" ] && continue 2;
done
fi
if [ -n "${GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION}" ] ; then
for isd in "${GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION[@]}" ; do
[ "${description_snapshot}" = "${isd}" ] && continue 2;
done
fi
# detect if /boot directory exists
[[ ! -d "$gbgmp/$snap_path_name/boot" ]] && continue;
local date_snapshot="${snap[@]:10:2}"
date_snapshots+=("$date_snapshot")
path_snapshots+=("$path_snapshot")
type_snapshots+=("$type_snapshot")
description_snapshots+=("$description_snapshot")
done
local id="${snap_path_name//[!0-9]}" # brutal way to get id: remove everything non-numeric
ids+=("$id")
# Find max length of a snapshot date, needed for pretty formatting
local max_date_length=0
for i in "${date_snapshots[@]}"; do
local length="${#i}"
[ "$length" -gt "$max_date_length" ] && max_date_length=$length
done
local entry="${snap[@]:10:2} | ${snap_path_name}"
entries+=("$entry")
# Find max length of a snapshot entry, needed for pretty formatting
local length="${#entry}"
[[ "$length" -gt "$max_entry_length" ]] && max_entry_length=$length
# Find max length of a snapshot name, needed for pretty formatting
local max_path_length=0
for i in "${path_snapshots[@]}"; do
local length="${#i}"
[ "$length" -gt "$max_path_length" ] && max_path_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
for i in "${type_snapshots[@]}"; do
local length="${#i}"
[ "$length" -gt "$max_type_length" ] && max_type_length=$length
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
# Find max length of a snapshot description, needed for pretty formatting
local max_description_length=0
for i in "${description_snapshots[@]}"; do
local length="${#i}"
[[ "$length" -gt "$max_description_length" ]] && max_description_length=$length
done
for i in "${!path_snapshots[@]}"; do
printf -v entry "%-${max_date_length}s | %-${max_path_length}s | %-${max_type_length}s | %-${max_description_length}s |" "${date_snapshots[$i]}" "${path_snapshots[$i]}" "${type_snapshots[$i]}" "${description_snapshots[$i]}"
echo "$entry"
done
IFS=$oldIFS
}
## Detect kernels in "/boot"
## Parse snapshots in snapshot_list
parse_snapshot_list()
{
snap_date=" $(echo "$item" | cut -d'|' -f1)" # column_1, first space is necessary for pretty formatting
snap_date_trim="$(trim "$snap_date")"
snap_dir_name="$(echo "$item" | cut -d'|' -f2)" # column_2
snap_dir_name_trim="$(trim "$snap_dir_name")"
snap_snapshot="$snap_dir_name" # Used by "title_format" function
snap_type="$(echo "$item" | cut -d'|' -f3)" # column_3
snap_description="$(echo "$item" | cut -d'|' -f4)" # column_4
}
## Detect kernels in "boot_directory"
detect_kernel()
{
list_kernel=()
@@ -318,60 +493,55 @@ detect_kernel()
for okernel in "${boot_dir}"/vmlinuz-* \
"${boot_dir}"/vmlinux-* \
"${boot_dir}"/kernel-* ; do
[[ ! -f "${okernel}" ]] && continue;
[ ! -f "${okernel}" ] && continue;
list_kernel+=("$okernel")
done
# Custom name kernel in GRUB_BTRFS_NKERNEL
if [ ! -z "${GRUB_BTRFS_NKERNEL}" ] ; then
# Custom name kernel in "GRUB_BTRFS_NKERNEL"
if [ -n "${GRUB_BTRFS_NKERNEL}" ] ; then
for ckernel in "${boot_dir}/${GRUB_BTRFS_NKERNEL[@]}" ; do
[[ ! -f "${ckernel}" ]] && continue;
[ ! -f "${ckernel}" ] && continue;
list_kernel+=("$ckernel")
done
fi
}
## Detect initramfs in "/boot"
## Detect initramfs in "boot_directory"
detect_initramfs()
{
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;
"${boot_dir}"/initramfs-* \
"${boot_dir}"/initrd-* ; do
[ ! -f "${oinitramfs}" ] && continue;
list_initramfs+=("$oinitramfs")
done
# Custom name initramfs in GRUB_BTRFS_NINIT
if [ ! -z "${GRUB_BTRFS_NINIT}" ] ; then
# Custom name initramfs in "GRUB_BTRFS_NINIT"
if [ -n "${GRUB_BTRFS_NINIT}" ] ; then
for cinitramfs in "${boot_dir}/${GRUB_BTRFS_NINIT[@]}" ; do
[[ ! -f "${cinitramfs}" ]] && continue;
[ ! -f "${cinitramfs}" ] && continue;
list_initramfs+=("$cinitramfs")
done
fi
if [ -z "${list_initramfs}" ]; then list_initramfs=(x); fi
}
## Detect microcode in "/boot"
## Detect microcode in "boot_directory"
detect_microcode()
{
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;
for oiucode in ${GRUB_EARLY_INITRD_LINUX_STOCK} ; do
oiucode="${boot_dir}/${oiucode}"
[ ! -f "${oiucode}" ] && continue;
list_ucode+=("$oiucode")
done
# Custom name microcode in GRUB_BTRFS_CUSTOM_MICROCODE
if [ ! -z "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
# Custom name microcode in "GRUB_BTRFS_CUSTOM_MICROCODE"
if [ -n "${GRUB_BTRFS_CUSTOM_MICROCODE}" ] ; then
for cucode in "${boot_dir}/${GRUB_BTRFS_CUSTOM_MICROCODE[@]}" ; do
[[ ! -f "${cucode}" ]] && continue
list_ucode+=("$cucode")
@@ -380,29 +550,40 @@ detect_microcode()
if [ -z "${list_ucode}" ]; then list_ucode=(x); fi
}
## Show full path snapshot or only name
path_snapshot()
{
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 in Grub-menu
declare -A title_column=( [date]=Date [snapshot]=Snapshot [type]=Type [description]=Description ) # Column title that appears in the header
title_format()
{
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
title_menu="|" # "|" is for visuals only
title_submenu="|" # "|" is for visuals only
[[ -z "${GRUB_BTRFS_TITLE_FORMAT}" ]] && GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description"); # Default parameters
for key in "${!GRUB_BTRFS_TITLE_FORMAT[@]}"; do
[[ ${GRUB_BTRFS_TITLE_FORMAT[$key],,} != "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key]}],,}" ]] && continue; # User used wrong parameter
declare -n var="snap_${GRUB_BTRFS_TITLE_FORMAT[$key],,}" # $var is a indirect variable
if [[ "${#var}" -lt "${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}" ]]; then # Add extra spaces if length of $var is smaller than the length of column, needed for pretty formatting
printf -v var "%-$(((${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}-${#var})+${#var}))s" "${var}";
fi
var="$(sed "s/'//g" <(echo "${var}"))"
title_menu+="${var}|"
title_submenu+=" $(trim "${var}") |"
done
}
# Adds a header to the grub-btrfs.cfg file
header_menu()
{
local header_entry=""
[[ -z "${GRUB_BTRFS_TITLE_FORMAT}" ]] && GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description"); # Default parameters
for key in "${!GRUB_BTRFS_TITLE_FORMAT[@]}"; do
[[ ${GRUB_BTRFS_TITLE_FORMAT[$key],,} != "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key]}],,}" ]] && continue; # User used wrong parameter
declare -n var="snap_${GRUB_BTRFS_TITLE_FORMAT[$key],,}" # $var is a indirect variable
# Center alignment, needed for pretty formatting
local lenght_title_column_left=$((${#var}-${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}))
((lenght_title_column_left%2)) && lenght_title_column_left=$((lenght_title_column_left+1)); # If the difference is an odd number, add an extra space
lenght_title_column_left=$((((lenght_title_column_left/2)+${#title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]})));
local lenght_title_column_right=$(((${#var}-lenght_title_column_left)+1)) #+1 is necessary for extra "|" character
header_entry+=$(printf "%${lenght_title_column_left}s%${lenght_title_column_right}s" "${title_column[${GRUB_BTRFS_TITLE_FORMAT[$key],,}]}" "|") # Final "|" is for visuals only
done
sed -i "1imenuentry '|${header_entry}' { echo }" "$grub_btrfs_directory/grub-btrfs.new" # First "|" is for visuals only
}
## List of kernels, initramfs and microcode in snapshots
@@ -411,143 +592,114 @@ boot_bounded()
# Initialize menu entries
IFS=$'\n'
for item in $(snapshot_list); do
[[ ${limit_snap_show} -le 0 ]] && break; # fix: limit_snap_show=0
[ "${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)
parse_snapshot_list
boot_dir="$grub_btrfs_mount_point/$snap_dir_name_trim$boot_directory"
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[@]##*"/"}")
detect_rootflags
title_format
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" # convert "boot_directory" to root of GRUB (e.g /boot become /)
insmods=("${list_insmods[@]##*"/"}")
make_menu_entries
# show snapshot found during run "grub-mkconfig"
if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
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;
# 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
}
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}")"
# Kernel (Original + custom kernel)
boot_dir_root_grub="$(make_system_path_relative_to_its_root "${boot_dir}")" # convert "boot_directory" to root of GRUB (e.g /boot become /)
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
[ "${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
parse_snapshot_list
detect_rootflags
title_format
make_menu_entries
# show snapshot found during run "grub-mkconfig"
if [[ "${GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND:-"true"}" = "true" ]]; then
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;
count_limit_snap=$((1+count_limit_snap))
[ "$count_limit_snap" -ge "$limit_snap_show" ] && 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"
rm -f "$grub_btrfs_directory/grub-btrfs.new"
true > "$grub_btrfs_directory/grub-btrfs.new" # Create a "grub-btrfs.new" file in "grub_btrfs_directory"
# Create a backup of the "$grub_btrfs_directory/grub-btrfs.cfg" file if exist
if [ -e "$grub_btrfs_directory/grub-btrfs.cfg" ]; then
mv -f "$grub_btrfs_directory/grub-btrfs.cfg" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
fi
# 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
[ ! -d "$grub_btrfs_mount_point" ] && mkdir -p "$grub_btrfs_mount_point"
mount -o ro,subvolid=5 /dev/disk/by-uuid/"$root_uuid" "$grub_btrfs_mount_point/" > /dev/null
trap "unmount_grub_btrfs_mount_point" EXIT # unmounting mount point on EXIT signal
count_warning_menuentries=0 # Count menuentries
count_limit_snap=0 # Count snapshots
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
[ "$(echo "$GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION}" | tr '[:upper:]' '[:lower:]')" = "true" ] && printf "Override boot partition detection : enable \n" >&2 && boot_separate;
if [ "$root_uuid" != "$boot_uuid" ] || [ "$root_uuid_subvolume" != "$boot_uuid_subvolume" ]; then boot_separate ; else boot_bounded ; fi
# Make a submenu in GRUB (grub.cfg)
cat << EOF
if [ ! -e "${grub_btrfs_search_directory}/grub-btrfs.cfg" ]; then
echo ""
else
submenu '${submenuname}' ${protection_authorized_users}${unrestricted_access_submenu}{
configfile "\${prefix}/grub-btrfs.cfg"
configfile "${grub_btrfs_search_directory}/grub-btrfs.cfg"
}
fi
EOF
### End
# Show warn, menuentries exceeds 250 entries
[ $count_warning_menuentries -ge 250 ] && printf "Generated %s total GRUB entries. You might experience issues loading snapshots menu in GRUB.\n" "${count_warning_menuentries}" >&2 ;
# Show total found snapshots
if [ "${GRUB_BTRFS_SHOW_TOTAL_SNAPSHOTS_FOUND:-"true"}" = "true" ] && [ -n "${count_limit_snap}" ] && [ "${count_limit_snap}" != "0" ]; then
printf "Found %s snapshot(s)\n" "${count_limit_snap}" >&2 ;
fi
# if no snapshot found, delete the "$grub_btrfs_directory/grub-btrfs.new" file and the "$grub_btrfs_directory/grub-btrfs.cfg.bkp" file and exit
if [ "${count_limit_snap}" = "0" ] || [ -z "${count_limit_snap}" ]; then
rm -f "$grub_btrfs_directory/grub-btrfs.new" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
print_error "No snapshots found."
fi
# Move "grub-btrfs.new" to "grub-btrfs.cfg"
header_menu
if "${bindir}/${GRUB_BTRFS_SCRIPT_CHECK:-grub-script-check}" "$grub_btrfs_directory/grub-btrfs.new"; then
cat "$grub_btrfs_directory/grub-btrfs.new" > "$grub_btrfs_directory/grub-btrfs.cfg"
rm -f "$grub_btrfs_directory/grub-btrfs.new" "$grub_btrfs_directory/grub-btrfs.cfg.bkp"
else
if [ -e "$grub_btrfs_directory/grub-btrfs.cfg.bkp" ]; then
mv -f "$grub_btrfs_directory/grub-btrfs.cfg.bkp" "$grub_btrfs_directory/grub-btrfs.cfg"
fi
print_error "Syntax errors were detected in generated ${grub_btrfs_directory}/grub-btrfs.new file. The old grub-btrfs.cfg file (if present) have been restored."
fi
# warn when this script is run but there is no entry in grub.cfg
grep "snapshots-btrfs" "${grub_directory}/grub.cfg" >/dev/null 2>&1 || printf "\nWARNING: '%s' needs to run at least once to generate the snapshots (sub)menu entry in grub the main menu. \
After that this script can run alone to generate the snapshot entries.\n\n" "${GRUB_BTRFS_MKCONFIG:-grub-mkconfig}" >&2 ;

122
Makefile
View File

@@ -2,35 +2,107 @@ PKGNAME ?= grub-btrfs
PREFIX ?= /usr
INITCPIO ?= false
SYSTEMD ?= true
OPENRC ?= false
BOOT_DIR_DEBIAN ?= /boot/grub
BOOT_DIR_FEDORA ?= /boot/grub2
GRUB_UPDATE_EXCLUDE ?= false
INSTALL_DOCS ?= true
SHARE_DIR = $(DESTDIR)$(PREFIX)/share
LIB_DIR = $(DESTDIR)$(PREFIX)/lib
BIN_DIR = $(DESTDIR)$(PREFIX)/bin
MAN_DIR = $(SHARE_DIR)/man
.PHONY: install uninstall help
TEMP_DIR = ./temp
.PHONY: install uninstall clean help
install:
@if test "$(shell id -u)" != 0; then \
echo "You are not root, run this target as root please."; \
exit 1; \
fi
@echo " Installing "
@echo
@echo " :::::::: ::::::::: ::: ::: ::::::::: ::::::::: ::::::::::: ::::::::: :::::::::: :::::::: "
@echo " :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+: "
@echo " +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ "
@echo " :#: +#++:++#: +#+ +:+ +#++:++#+ +#++:++#++:++ +#++:++#+ +#+ +#++:++#: :#::+::# +#++:++#++ "
@echo " +#+ +#+# +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+ "
@echo " #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# #+# "
@echo " ######## ### ### ######## ######### ######### ### ### ### ### ######## "
@echo
@echo " For further information visit https://github.com/Antynea/grub-btrfs or read the man page: 'man grub-btrfs'"
@echo
@rm -rf "${TEMP_DIR}"
@mkdir "${TEMP_DIR}"
@chmod 777 ${TEMP_DIR}
@cp manpages/grub-btrfs.8.man ${TEMP_DIR}/grub-btrfs.8
@if test "$(INSTALL_DOCS)" = true; then \
echo "Installing manpages..."; \
install -Dm644 -t "${MAN_DIR}/man8" "${TEMP_DIR}/grub-btrfs.8"; \
fi
@cp manpages/grub-btrfsd.8.man ${TEMP_DIR}/grub-btrfsd.8
@if test "$(INSTALL_DOCS)" = true; then \
install -Dm644 -t "${MAN_DIR}/man8" "${TEMP_DIR}/grub-btrfsd.8"; \
fi
@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
@install -Dm744 -t "$(BIN_DIR)/" grub-btrfsd;
@# Systemd init system
@if test "$(SYSTEMD)" = true; then \
echo "Installing systemd .service file"; \
install -Dm644 -t "$(LIB_DIR)/systemd/system/" grub-btrfsd.service; \
fi
@# OpenRC init system
@if test "$(OPENRC)" = true; then \
echo "Installing openRC init.d & conf.d file"; \
install -Dm744 grub-btrfsd.initd "$(DESTDIR)/etc/init.d/grub-btrfsd"; \
install -Dm644 grub-btrfsd.confd "$(DESTDIR)/etc/conf.d/grub-btrfsd"; \
fi
@# Arch Linux like distros only :
@if test "$(INITCPIO)" = true; then \
echo "Installing initcpio hook"; \
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"
@if test "$(INSTALL_DOCS)" = true; then \
echo "Installing docs..."; \
install -Dm644 -t "$(SHARE_DIR)/licenses/$(PKGNAME)/" LICENSE; \
install -Dm644 -t "$(SHARE_DIR)/doc/$(PKGNAME)/" README.md; \
install -Dm644 "initramfs/readme.md" "$(SHARE_DIR)/doc/$(PKGNAME)/initramfs-overlayfs.md"; \
fi
@if command -v grub-mkconfig > /dev/null && [ -e "$(BOOT_DIR_DEBIAN)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
echo "Updating the GRUB menu..."; \
grub-mkconfig -o "$(BOOT_DIR_DEBIAN)/grub.cfg"; \
fi
@if command -v grub2-mkconfig > /dev/null && [ -e "$(BOOT_DIR_FEDORA)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
echo "Updating the GRUB menu..."; \
grub2-mkconfig -o "$(BOOT_DIR_FEDORA)/grub.cfg"; \
fi
uninstall:
@echo "Uninstalling grub-btrfs"
@if test "$(shell id -u)" != 0; then \
echo "You are not root, run this target as root please."; \
exit 1; \
fi
@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)/systemd/system/grub-btrfsd.service"
@rm -f "$(BIN_DIR)/grub-btrfsd;"
@rm -f "$(DESTDIR)/etc/init.d/grub-btrfsd;"
@rm -f "$(DESTDIR)/etc/conf.d/grub-btrfsd;"
@rm -f "$(LIB_DIR)/initcpio/install/grub-btrfs-overlayfs"
@rm -f "$(LIB_DIR)/initcpio/hooks/grub-btrfs-overlayfs"
@rm -f "$(MAN_DIR)/man8/grub-btrfs.8.bz2"
@rm -f "$(MAN_DIR)/man8/grub-btrfsd.8.bz2"
@# 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" || :; \
@@ -43,21 +115,39 @@ uninstall:
@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" || :
@if command -v grub-mkconfig > /dev/null && [ -e "$(BOOT_DIR_DEBIAN)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
echo "Updating the GRUB menu..."; \
grub-mkconfig -o "$(BOOT_DIR_DEBIAN)/grub.cfg"; \
fi
@if command -v grub2-mkconfig > /dev/null && [ -e "$(BOOT_DIR_FEDORA)/grub.cfg" ] && test "$(GRUB_UPDATE_EXCLUDE)" = false; then \
echo "Updating the GRUB menu..."; \
grub2-mkconfig -o "$(BOOT_DIR_FEDORA)/grub.cfg"; \
fi
clean:
@echo "Deleting ./temp"
@rm -rf "${TEMP_DIR}"
help:
@echo
@echo "Usage: $(MAKE) [ <parameter>=<value> ... ] [ <action> ]"
@echo "Example: $(MAKE) OPENRC=true SYSTEMD=false install"
@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 " parameter | type | description | defaults"
@echo " --------------------+------+-------------------------------------------------------+----------------------------"
@echo " DESTDIR | path | install destination | <unset>"
@echo " PREFIX | path | system tree prefix | '/usr'"
@echo " BOOT_DIR_DEBIAN | path | boot data location (Debian, Ubuntu, Gentoo, Arch...) | '/boot/grub'"
@echo " BOOT_DIR_FEDORA | path | boot data location (Fedora, RHEL, CentOS, Rocky...) | '/boot/grub2'"
@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 distributed package | 'grub-btrfs'"
@echo " INITCPIO | bool | include mkinitcpio hook | false"
@echo " SYSTEMD | bool | include unit files | true"
@echo " OPENRC | bool | include OpenRc daemon | false"
@echo " GRUB_UPDATE_EXCLUDE | bool | Do not update grub after installation | false"
@echo

356
README.md
View File

@@ -1,79 +1,329 @@
[![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 4.xx of grub-btrfs
##### BTC donation address: `1Lbvz244WA8xbpHek9W2Y12cakM6rDe5Rt`
##
### Description
Improves Grub by adding "btrfs snapshots" to the Grub menu.
- - -
### 🔎 Description:
grub-btrfs improves the grub bootloader by adding a btrfs snapshots sub-menu, allowing the user to boot into snapshots.
You can start your system on a "snapshot" from the Grub menu.
Supports manual snapshots, snapper, timeshift ...
grub-btrfs supports manual snapshots as well as snapper, timeshift, and yabsnap created snapshots.
##### Warning: booting on read-only snapshots can be tricky
##### Warning: booting 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.
If you wish to use read-only snapshots, `/var/log` or even `/var` must be on a separate subvolume.
Otherwise, make sure your snapshots are writable.
See [this ticket](https://github.com/Antynea/grub-btrfs/issues/92) for more info.
This project includes its own solution.
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.
- - -
### What features does grub-btrfs have?
* Automatically lists snapshots existing on the btrfs root partition.
* Automatically detect if `/boot` is in a separate partition.
* Automatically detect kernel, initramfs and Intel/AMD microcode in `/boot` directory within snapshots.
* Automatically create corresponding menu entries in `grub.cfg`
* Automatically detect the type/tags/triggers and descriptions/comments of Snapper/Timeshift/Yabsnap snapshots.
* Automatically generate `grub.cfg` if you use the provided Systemd/ OpenRC service.
##
### Installation :
- - -
### 🛠️ Installation:
#### Arch Linux
The package is available in the extra repository [grub-btrfs](https://archlinux.org/packages/extra/any/grub-btrfs/)
```
pacman -S grub-btrfs
```
#### Manual
#### Gentoo
grub-btrfs is only available in the Gentoo User Repository (GURU) and not in the official Gentoo repository.
If you have not activated the GURU yet, do so by running:
```
emerge -av app-eselect/eselect-repository
eselect repository enable guru
emaint sync -r guru
```
If you are using Systemd on Gentoo, make sure the USE-Flag `systemd` is set. (Either globally in make.conf or in package.use for the package app-backup/grub-btrfs)
Without Systemd USE-Flag the OpenRC-daemon of grub-btrfs will be installed.
* Run `make install` or look into Makefile for instructions on where to put each file.
Emerge grub-btrfs via
`emerge app-backup/grub-btrfs`
NOTE: Generate your Grub menu after installation for the changes to take effect.
On Arch Linux use `grub-mkconfig -o /boot/grub/grub.cfg`.
#### Kali Linux
[grub-btrfs](http://pkg.kali.org/pkg/grub-btrfs) is available in the Kali Linux repository and can be installed with:
```
apt install grub-btrfs
```
Booting into read-only snapshots is fully supported when choosing btrfs as the file system during a standard Kali Linux installation following [this walk-through](https://www.kali.org/docs/installation/btrfs/).
##
### Customization:
#### Manual installation
* Run `make install`
* Run `make help` to check what options are available.
* Dependencies:
* [btrfs-progs](https://archlinux.org/packages/core/x86_64/btrfs-progs/)
* [grub](https://archlinux.org/packages/core/x86_64/grub/)
* [bash >4](https://archlinux.org/packages/core/x86_64/bash/)
* [gawk](https://archlinux.org/packages/core/x86_64/gawk/)
* (only when using the grub-btrfsd daemon)[inotify-tools](https://archlinux.org/packages/extra/x86_64/inotify-tools/)
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.
- - -
### 📚 Manual usage of grub-btrfs
To manually generate grub snapshot entries you can run `sudo /etc/grub.d/41_snapshots-btrfs` which updates `grub-btrfs.cfg`. You then need to regenerate the GRUB configuration by running one of the following commands:
##
### 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.
* On **Arch Linux** or **Gentoo** use `grub-mkconfig -o /boot/grub/grub.cfg`.
* On **Fedora** use `grub2-mkconfig -o /boot/grub2/grub.cfg`
* On **Debian and Ubuntu based** distributions `update-grub` is a script that runs `grub-mkconfig ...`
This process can be automated to occur whenever you create or delete snapshots but this process is slightly different depending upon your distributions choice on init system. See the relevant instructions for your init system below.
### ⚙️ Customization:
You have the possibility to modify many parameters in `/etc/default/grub-btrfs/config`.
For further information see [config file](https://github.com/Antynea/grub-btrfs/blob/master/config) or `man grub-btrfs`
#### Warning:
Some file locations and command names differ from distribution to distribution. Initially the configuration is set up to work with Arch and Gentoo (and many other distributions) out of the box, which are using the `grub-mkconfig` command.
However Fedora, for example, uses a different command, `grub2-mkconfig`.
Edit the `GRUB_BTRFS_MKCONFIG` variable in `/etc/default/grub-btrfs/config` file to reflect this. (e.g. `GRUB_BTRFS_MKCONFIG=/sbin/grub2-mkconfig` for Fedora)
On most distributions, the grub installation resides in `/boot/grub`. If grub is installed in a different place, change the variable `GRUB_BTRFS_MKCONFIG` in the config file accordingly. For Fedora this is `GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"`. The command to check the grub scripts is different on some system, for Fedora it is `GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check`
#### Customization of the grub-btrfsd daemon
Grub-btrfs comes with a daemon script that automatically updates the grub menu when it sees a snapshot being created or deleted in a directory it is given via command line. You must install `inotify-tools` before you can use grub-btrfsd.
The daemon can be configured by passing different command line arguments to it.
The available arguments are:
* `SNAPSHOTS_DIRS`
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
E.g. for Snapper or Yabsnap this would be `/.snapshots`. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
This argument is not necessary to provide if `--timeshift-auto` is set.
* `-c / --no-color`
Disable colors in output.
* `-l / --log-file`
This arguments specifies a file where grub-btrfsd should write log messages.
* `-r / --recursive`
Watch the snapshots directory recursively
* `-s / --syslog`
* `-o / --timeshift-old`
Look for snapshots in `/run/timeshift/backup/timeshift-btrfs` instead of `/run/timeshift/$PID/backup/timeshift-btrfs.` This is to be used for Timeshift versions <22.06. You must also use `--timeshift-auto` if using this option.
* `-t / --timeshift-auto`
This is a flag to activate the auto-detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to `/run/timeshift/$PID/backup/timeshift-btrfs`. Where `$PID` is the process ID of the currently running Timeshift session. The PID changes every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument `SNAPSHOTS_DIRS` has no effect.
* `-v / --verbose`
Let the log of the daemon be more verbose
* `-h / --help`
Displays a short help message.
- - -
### 🪀 Automatically update grub upon snapshot creation or deletion
Grub-btrfsd is a daemon that watches the snapshot directory for you and updates the grub menu automatically every time a snapshot is created or deleted.
By default this daemon watches the directory `/.snapshots` for changes (creation or deletion of snapshots) and triggers the grub menu creation and re-installation of grub if any changes are noticed.
Therefore, if Snapper or Yabsnap is used with its default directory, the daemon can just be started and nothing needs to be configured. See the instructions below to configure grub-btrfsd for use with Timeshift or when using an alternative snapshots directory with Snapper/Yabsnap.
- - -
#### grub-btrfsd systemd instructions
To start the daemon run:
```bash
sudo systemctl start grub-btrfsd
```
To activate it during system startup, run:
```bash
sudo systemctl enable grub-btrfsd
```
##### 💼 Snapshots not in `/.snapshots` when using systemd
By default the daemon is watching the directory `/.snapshots`. If the daemon should watch a different directory, it can be edited with:
```bash
sudo systemctl edit --full grub-btrfsd
```
You need to edit the `/.snapshots` part in the line that says `ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots`.
This is what the file should look like afterwards:
``` bash
[Unit]
Description=Regenerate grub-btrfs.cfg
[Service]
Type=simple
LogLevelMax=notice
# 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
# Start the daemon, usage of it is:
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
# Optional arguments:
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
# -o, --timeshift-old Activate for timeshift versions <22.06
# -l, --log-file Specify a logfile to write to
# -v, --verbose Let the log of the daemon be more verbose
# -s, --syslog Write to syslog
ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots
[Install]
WantedBy=multi-user.target
```
When done, the service should be restarted with:
``` bash
sudo systemctl restart grub-btrfsd
```
##### 🌟 Using Timeshift with systemd
Newer Timeshift versions (>= 22.06) create a new directory named after their process ID in `/run/timeshift` every time they are started. The PID will be different every time.
Therefore the daemon cannot simply watch a directory. It monitors `/run/timeshift` and if a directory is created it gets Timeshifts current PID then watches a directory in that newly created directory from Timeshift.
To activate this mode of the daemon, `--timeshift-auto` must be passed to the daemon as a command line argument.
To pass `--timeshift-auto` to grub-btrfsd, the .service file of grub-btrfsd can be edited with
```bash
sudo systemctl edit --full grub-btrfsd
```
The line that contains:
```bash
ExecStart=/usr/bin/grub-btrfsd /.snapshots --syslog
```
Should be modified to read:
``` bash
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
```
The modified file should look like this:
``` bash
[Unit]
Description=Regenerate grub-btrfs.cfg
[Service]
Type=simple
LogLevelMax=notice
# 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
# Start the daemon, usage of it is:
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
# Optional arguments:
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
# -l, --log-file Specify a logfile to write to
# -v, --verbose Let the log of the daemon be more verbose
# -s, --syslog Write to syslog
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto
[Install]
WantedBy=multi-user.target
```
If you are using an older release of Timeshift (before 22.06), you also need to add `--timeshift-old` so that your ExecStart line would look like:
```
ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto --timeshift-old
```
When done, the service must be restarted with:
``` bash
sudo systemctl restart grub-btrfsd
```
Note:
You can view your change with `systemctl cat grub-btrfsd`.
To revert all the changes use `systemctl revert grub-btrfsd`.
- - -
#### grub-btrfsd OpenRC instructions
To start the daemon run:
```bash
sudo rc-service grub-btrfsd start
```
To activate it during system startup, run:
```bash
sudo rc-config add grub-btrfsd default
```
##### 💼 Snapshots not in `/.snapshots` for OpenRC
By default the daemon is watching the directory `/.snapshots`. If the daemon should watch a different directory, it can be edited by passing different arguments to it.
Arguments are passed to grub-btrfsd via the file `/etc/conf.d/grub-btrfsd`.
The variable `snapshots` defines the path the daemon will monitor for snapshots.
After editing, the file should look like this:
``` bash
# Copyright 2022 Pascal Jaeger
# Distributed under the terms of the GNU General Public License v3
## Where to locate the root snapshots
snapshots="/.snapshots" # Snapper in the root directory
#snapshots="/run/timeshift/backup/timeshift-btrfs/snapshots" # Timeshift < v22.06
## Optional arguments to run with the daemon
# Append options to this like this:
# optional_args="--syslog --timeshift-auto --verbose"
# Possible options are:
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory for timeshift >= 22.06
# -o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)
# -l, --log-file Specify a logfile to write to
# -v, --verbose Let the log of the daemon be more verbose
# -s, --syslog Write to syslog
optional_args="--syslog"
```
After that, the daemon should be restarted with:
``` bash
sudo rc-service grub-btrfsd restart
```
##### 🔒 Snapshots on LUKS encrypted devices
By default, grub-btrfs generates entries that does not load modules for dealing with encrypted devices.
Enable the `GRUB_BTRFS_ENABLE_CRYPTODISK` variable in `/etc/default/grub-btrfs/config` to load said modules and then execute the steps to mount encrypted root after selecting the snapshot.
- - -
### Troubleshooting
If you experience problems with grub-btrfs don't hesitate [to file an issue](https://github.com/Antynea/grub-btrfs/issues/new/choose).
#### What version of grub-btrfs am I running?
When requesting help or reporting bugs in grub-btrfs, please run:
``` bash
sudo /etc/grub.d/41_snapshots-btrfs --version
```
or
``` bash
sudo /usr/bin/grub-btrfsd --help
```
to get the currently running version of grub-btrfs and include this information in your ticket.
#### Running grub-btrfsd in verbose mode
If you have problems with the daemon, you can run it with the `--verbose`-flag. To do so you can run:
``` bash
sudo /usr/bin/grub-btrfsd --verbose --timeshift-auto` (for timeshift)
# or
sudo /usr/bin/grub-btrfsd /.snapshots --verbose` (for snapper/yabsnap)
```
Or pass `--verbose` to the daemon using the Systemd .service file or the OpenRC conf.d file respectively.
For additional information on the daemon and its arguments, run `grub-btrfsd -h` or `man grub-btrfsd`
- - -
### Development
Grub-btrfs uses a rudimentary system of automatic versioning to tell apart different commits. This is helpful when users report problems and it is not immediately clear what version they are using.
We therefore have the following script in `.git/hooks/pre-commit`:
``` bash
#!/bin/sh
echo "Doing pre commit hook with version bump"
version="$(git describe --tags --abbrev=0)-$(git rev-parse --abbrev-ref HEAD)-$(date -u -Iseconds)"
echo "New version is ${version}"
sed -i "s/GRUB_BTRFS_VERSION=.*/GRUB_BTRFS_VERSION=${version}/" config
git add config
```
This automatically sets the version in the `config`-file to `[lasttag]-[branch-name]-[current-date-in-UTC]`.
In order to create a Tag we don't want to have this long version. In this case we set the version manually in `config` and commit with `git commit --no-verify`. This avoids running the hook.
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)
* [Maxim Baz](https://github.com/maximbaz)
* [Schievel1](https://github.com/Antynea/grub-btrfs/discussions/173#discussioncomment-1438790)
* [All contributors](https://github.com/Antynea/grub-btrfs/graphs/contributors)
##
- - -

86
config
View File

@@ -1,5 +1,8 @@
#!/usr/bin/env bash
GRUB_BTRFS_VERSION=4.13-yabsnap_info_support-2024-03-06T13:43:57+00:00
# Disable grub-btrfs.
# Default: "false"
#GRUB_BTRFS_DISABLE="true"
@@ -8,18 +11,10 @@
# 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"
# Shows/Hides "date" "snapshot" "type" "description" in the Grub menu, custom order available.
# Default: ("date" "snapshot" "type" "description")
#GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")
# Limit the number of snapshots populated in the GRUB menu.
# Default: "50"
@@ -54,7 +49,14 @@
# 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.
# Additional kernel command line parameters that should be passed to the kernel
# when booting a snapshot.
# For dracut based distros this could be useful to pass "rd.live.overlay.overlayfs=1"
# or "rd.live.overlay.readonly=1" to the Kernel for booting snapshots read only.
# Default: ""
#GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"
# Comma separated 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.
@@ -72,19 +74,31 @@ GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@")
# 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")
GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker" "var/lib/containers" "@var/lib/containers" "@/var/lib/containers")
# Ignore specific type/tag of snapshot during run "grub-mkconfig".
# For snapper:
# Type = single, pre, post.
# For Timeshift:
# Tag = boot, ondemand, hourly, daily, weekly, monthly.
# For yabsnap:
# Trigger = S, I, U.
# Default: ("")
#GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("")
# Ignore specific description of snapshot during run "grub-mkconfig".
# e.g: timeline
# Default: ("")
#GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("")
# 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.
# either located at the system root or on a separate partition or in a subvolume,
# Change to "true" if your boot partition isn't detected as separate.
# 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"
@@ -93,6 +107,24 @@ GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/doc
# Default: "/boot"
#GRUB_BTRFS_BOOT_DIRNAME="/boot"
# Location where grub-btrfs.cfg should be saved.
# Some distributions (like OpenSuSE) store those files at the snapshot directory
# instead of boot. Be aware that this directory must be available for grub during
# startup of the system.
# Default: $GRUB_BTRFS_GRUB_DIRNAME
#GRUB_BTRFS_GBTRFS_DIRNAME="/boot/grub"
# Location of the directory where Grub searches for the grub-btrfs.cfg file.
# Some distributions (like OpenSuSE) store those file at the snapshot directory
# instead of boot. Be aware that this directory must be available for grub during
# startup of the system.
# Default: "\${prefix}" # This is a grub variable that resolves to where grub is
# installed. (like /boot/grub, /boot/efi/grub)
# NOTE: If variables of grub are used here (like ${prefix}) they need to be escaped
# with `\` before the `$`
#GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"
# 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,
@@ -102,10 +134,16 @@ GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/doc
# Default: grub-mkconfig
#GRUB_BTRFS_MKCONFIG=/usr/bin/grub2-mkconfig
# Snapper
# Snapper's config name to use
# Default: "root"
#GRUB_BTRFS_SNAPPER_CONFIG="root"
# Name of grub-script-check command, use by "grub-btrfs"
# Might be 'grub2-script-check' on some systems (Fedora ...)
# For example, on Fedora : "grub2-script-check"
# Default: grub-script-check
#GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check
# Path of grub-mkconfig_lib file, use by "grub-btrfs"
# Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (Opensuse ...)
# Default: /usr/share/grub/grub-mkconfig_lib
#GRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub-mkconfig_lib
# Password protection management for submenu,snapshots
# Refer to the Grub documentation https://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation
@@ -120,3 +158,7 @@ GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/doc
# doesn't work if GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS isn't empty
# Default: "false"
#GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"
# Enable booting from snapshots stored on LUKS encrypted devices
# Default: "false"
#GRUB_BTRFS_ENABLE_CRYPTODISK="true"

View File

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

View File

@@ -1,11 +0,0 @@
[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'

340
grub-btrfsd Executable file
View File

@@ -0,0 +1,340 @@
#!/usr/bin/env bash
# Copyright 2023 Pascal Jaeger
# Distributed under the terms of the GNU General Public License v3
# Update GRUB when new BTRFS snapshots are created.
sighandler() {
trap '""' SIGINT SIGTERM
vlog "Parent $$: Received signal SIGINT/ SIGTERM"
kill 0
wait
exit 0
}
setcolors() {
if [ "${1}" = true ]; then
GREEN=$'\033[0;32m'
RED=$'\033[0;31m'
CYAN=$'\033[;36m'
RESET=$'\033[0m'
fi
if [ "${1}" = false ]; then
GREEN=$'\033[0;0m'
RED=$'\033[0;0m'
CYAN=$'\033[;0m'
RESET=$'\033[0m'
fi
}
print_help() {
echo "${CYAN}[?] Usage:"
echo "${0##*/} [-h, --help] [-c, --no-color] [-l, --log-file LOG_FILE] [-r, --recursive] [-s, --syslog] [-t, --timeshift-auto] [-v, --verbose] SNAPSHOTS_DIRS"
echo
echo "SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto"
echo
echo "Optional arguments:"
echo "-c, --no-color Disable colors in output"
echo "-l, --log-file Specify a logfile to write to"
echo "-r, --recursive Watch snapshots directory recursively"
echo "-s, --syslog Write to syslog"
echo "-o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)"
echo "-t, --timeshift-auto Automatically detect Timeshifts snapshot directory"
echo "-v, --verbose Let the log of the daemon be more verbose"
echo "-h, --help Display this message"
echo
echo "Version ${GRUB_BTRFS_VERSION}${RESET}"
}
log() {
echo "${2}"$1"${RESET}"
if [ ${syslog} = true ]; then
logger -p user.notice -t ${0##*/}"["$$"]" "$1"
fi
if [ ${#logfile} -gt 1 ]; then
echo "$(date) ${1}" >> "${logfile}"
fi
}
vlog() {
if [ ${verbose} = true ]; then
echo "${2}"$1"${RESET}"
if [ ${syslog} = true ]; then
logger -p user.notice -t ${0##*/} "$1"
fi
if [ ${#logfile} -gt 1 ]; then
echo "$(date) ${1}" >> "${logfile}"
fi
fi
}
err() {
echo "${2}"${1}"${RESET}" >&2
if [ ${syslog} = true ]; then
logger -p user.error -t ${0##*/} "$1"
fi
if [ ${#logfile} -gt 1 ]; then
echo "$(date) error: ${1}" >> "${logfile}"
fi
}
parse_arguments() {
while getopts :l:ctvrsh-: opt; do
case "$opt" in
-)
case "${OPTARG}" in
no-color)
setcolors false
;;
log-file)
logfile="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
;;
timeshift-auto)
timeshift_auto=true
;;
timeshift-old)
timeshift_old=true
;;
verbose)
verbose=true
;;
recursive)
recursive=true
;;
syslog)
syslog=true
;;
help)
print_help
exit 0
;;
*)
if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
err "[!] Unknown option --${OPTARG}" "${RED}" >&2
echo
fi
print_help
exit 1
;;
esac;;
c)
setcolors false
;;
l)
logfile="${OPTARG}"
;;
t)
timeshift_auto=true
;;
o)
timeshift_old=true
;;
v)
verbose=true
;;
r)
recursive=true
;;
s)
syslog=true
;;
h)
print_help
exit 0
;;
*)
if [ "$OPTERR" = 1 ] || [ "${optspec:0:1}" = ":" ]; then
err "[!] Non-option argument: '-${OPTARG}'" "${RED}" >&2
echo
fi
print_help
exit 1
;;
esac
done
}
checks() {
# check if inotify exists, see issue #227
if ! command -v inotifywait >/dev/null 2>&1; then
err "[!] inotifywait was not found, exiting. Is inotify-tools installed?" "${RED}" >&2
exit 1
fi
if [ ${timeshift_auto} = false ] && [ ${timeshift_old} = true ]; then
err "[!] Flag --timeshift-old requires flag --timeshift-auto" "${RED}" >&2
exit 1
fi
if ! [ ${timeshift_auto} = true ]; then
for snapdir in "${snapdirs[@]}"
do
if ! [ -d ${snapdir} ]; then
err "[!] No directory found at ${snapdir}" "${RED}" >&2
err "[!] Please specify a valid snapshot directory" "${RED}" >&2
exit 1
fi
done
fi
}
setup() {
if [ ${#logfile} -gt 1 ]; then
touch "${logfile}"
echo "GRUB-BTRFSD log $(date)" >> "${logfile}"
fi
if [ ${verbose} = true ]; then
inotify_qiet_flag=""
else
inotify_qiet_flag=" -q -q "
fi
if [ ${recursive} = true ]; then
inotify_recursive_flag=" -r "
else
inotify_recursive_flag=""
fi
if [ ${timeshift_auto} = true ]; then
watchtime=15
[ -d /run/timeshift ] || mkdir /run/timeshift
else
watchtime=0
fi
}
create_grub_menu() {
# create the grub submenu of the whole grub menu, depending on whether the submenu already exists
# and gives feedback if it worked
if grep "snapshots-btrfs" "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}"/grub.cfg; then
if /etc/grub.d/41_snapshots-btrfs; then
log "Grub submenu recreated" "${GREEN}"
else
err "[!] Error during grub submenu creation (grub-btrfs error)" "${RED}"
fi
else
if ${GRUB_BTRFS_MKCONFIG:-grub-mkconfig} -o "${GRUB_BTRFS_GRUB_DIRNAME:-/boot/grub}"/grub.cfg; then
log "Grub menu recreated" "${GREEN}"
else
err "[!] Error during grub menu creation (grub/ grub-btrfs error)" "${RED}"
fi
fi
}
set_snapshot_dir() {
# old timeshift has it's snapshot dir in a different location
if [ "${timeshift_old}" = true ]; then
snapdir="/run/timeshift/backup/timeshift-btrfs/snapshots"
else
snapdir="/run/timeshift/${timeshift_pid}/backup/timeshift-btrfs/snapshots"
fi
}
daemon_function() {
trap 'vlog "$BASHPID: Received SIGINT/ SIGTERM"; exit 0' SIGINT SIGTERM
# start the actual daemon
snapdir=$1
vlog "Subdaemon function started, PID: $BASHPID" "${GREEN}"
vlog "${BASHPID}: Entering infinite while for $snapdir" "${GREEN}"
vlog "${BASHPID}: Snapshot dir watchtimeout: $watchtime"
while true; do
runs=false
if [ ${timeshift_auto} = true ] && ! [ "${timeshift_pid}" -gt 0 ] ; then
# watch the timeshift folder for a folder that is created when timeshift starts up
sleep 1 # for safety so the outer while is not going crazy
if [ "${timeshift_pid}" -eq -2 ]; then
log "${BASHPID}: detected timeshift shutdown"
fi
timeshift_pid=$(ps ax | awk '{sub(/.*\//, "", $5)} $5 ~ /timeshift/ {print $1}')
if [ "${#timeshift_pid}" -gt 0 ]; then
set_snapshot_dir
log "${BASHPID}: detected running Timeshift at daemon startup, PID is: $timeshift_pid"
vlog "${BASHPID}: new snapshots directory is $snapdir"
else
log "Watching /run/timeshift for timeshift to start"
inotifywait ${inotify_qiet_flag} -e create -e delete /run/timeshift && {
sleep 1
timeshift_pid=$(ps ax | awk '{sub(/.*\//, "", $5)} $5 ~ /timeshift/ {print $1}')
set_snapshot_dir
log "${BASHPID}: detected Timeshift startup, PID is: $timeshift_pid" "${CYAN}"
vlog "${BASHPID}: new snapshots directory is $snapdir" "${CYAN}"
(create_grub_menu) # create the grub menu once immediately in a forking process. Snapshots from commandline using timeshift --create need this
}
fi
runs=false
else
while [ -d "$snapdir" ]; do
# watch the actual snapshots folder for a new snapshot or a deletion of a snapshot
if [ ${runs} = false ] && [ ${verbose} = false ]; then
log "${BASHPID}: Watching $snapdir for new snapshots..." "${CYAN}"
else
vlog "${BASHPID}: Watching $snapdir for new snapshots..." "${CYAN}"
fi
runs=true
inotifywait ${inotify_qiet_flag} ${inotify_recursive_flag} -e create -e delete -e unmount -t "$watchtime" "$snapdir" && {
log "${BASHPID}: Detected snapshot creation/ deletion, recreating Grub menu" "${CYAN}"
sleep 5
create_grub_menu
}
sleep 1
done
timeshift_pid=-2
fi
if ! [ ${timeshift_auto} = true ] && ! [ -d "${snapdir}" ] ; then # in case someone deletes the snapshots folder (in snapper mode) to prevent the while loop from going wild
break
fi
done
}
main() {
# init
timeshift_pid=-1
watchtime=0
logfile=0
snapshots=-1
timeshift_auto=false
timeshift_old=false
verbose=false
syslog=false
recursive=false
trap sighandler SIGINT SIGTERM
setcolors true # normally we want colors
sysconfdir="/etc"
grub_btrfs_config="${sysconfdir}/default/grub-btrfs/config"
# source config file
[ -f "$grub_btrfs_config" ] && . "$grub_btrfs_config"
[ -f "${sysconfdir}/default/grub" ] && . "${sysconfdir}/default/grub"
parse_arguments "${@}"
shift $(( OPTIND - 1 ))
snapdirs=( "${@}" )
vlog "Arguments:"
vlog "Snapshot directories: ${snapdirs[*]}"
vlog "Timestift autodetection: $timeshift_auto"
vlog "Timeshift old: $timeshift_old"
vlog "Logfile: $logfile"
vlog "Recursive: $recursive"
checks
setup
log "grub-btrfsd starting up..." "${GREEN}"
if [ ${timeshift_auto} = true ] ; then
daemon_function "timeshift" &
else
# for all dirs that got passed to the script, start a new fork with that dir
for snapdir in "${snapdirs[@]}"
do
vlog "starting daemon watching $snapdir..."
daemon_function "${snapdir}" &
done
fi
wait # wait for forks to finish, kill child forks if SIGTERM is sent
exit 0
}
main "${@}"

17
grub-btrfsd.confd Normal file
View File

@@ -0,0 +1,17 @@
# Copyright 2023 Pascal Jaeger
# Distributed under the terms of the GNU General Public License v3
## Where to locate the root snapshots
snapshots="/.snapshots" # Snapper in the root directory
#snapshots="/run/timeshift/backup/timeshift-btrfs/snapshots" # Timeshift < v22.06
## Optional arguments to run with the daemon
# Append options to this like this:
# optional_args="--syslog --timeshift-auto --verbose"
# Possible options are:
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory for timeshift >= 22.06
# -o, --timeshift-old Look for snapshots in directory of Timeshift <v22.06 (requires --timeshift-auto)
# -l, --log-file Specify a logfile to write to
# -v, --verbose Let the log of the daemon be more verbose
# -s, --syslog Write to syslog
optional_args="--syslog"

13
grub-btrfsd.initd Executable file
View File

@@ -0,0 +1,13 @@
#!/sbin/openrc-run
# Copyright 2023 Pascal Jaeger
# Distributed under the terms of the GNU General Public License v3
name="grub-btrfs daemon"
command="/usr/bin/grub-btrfsd"
command_args="$optional_args ${snapshots}"
pidfile="/run/{RC_SVCNAME}.pid"
command_background=true
depend() {
use localmount
}

23
grub-btrfsd.service Normal file
View File

@@ -0,0 +1,23 @@
[Unit]
Description=Regenerate grub-btrfs.cfg
[Service]
Type=simple
LogLevelMax=notice
# 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
# Start the daemon, usage of it is:
# grub-btrfsd [-h, --help] [-t, --timeshift-auto] [-l, --log-file LOG_FILE] SNAPSHOTS_DIRS
# SNAPSHOTS_DIRS Snapshot directories to watch, without effect when --timeshift-auto
# Optional arguments:
# -t, --timeshift-auto Automatically detect Timeshifts snapshot directory
# -o, --timeshift-old Activate for timeshift versions <22.06
# -l, --log-file Specify a logfile to write to
# -v, --verbose Let the log of the daemon be more verbose
# -s, --syslog Write to syslog
ExecStart=/usr/bin/grub-btrfsd --syslog /.snapshots
[Install]
WantedBy=multi-user.target

View File

@@ -39,7 +39,11 @@ You notice that the name of the `hook` must match the name of the 2 installed fi
Re-generate your initramfs
`mkinitcpio -P` (option -P means, all preset present in `/etc/mkinitcpio.d`)
#### Dracut based distros
Distributions that use Dracut to make their initramfs (many of the Fedora based Distros) simply have to pass either `rd.live.overlay.readonly=1` (to boot into the snapshot read only) or `rd.live.overlay.overlayfs=1` (to act like a livedisk, that is files can be changed but changes will be lost on the next boot) to their kernel command line in grub.
Grub-btrfs provides the variable `GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS` to add any command to the kernel command line. Set it to `GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"` to make snapshots immutable when booted into.
After changing this run `sudo /etc/grub.d/41_snapshots-btrfs` to generate a new snapshot-submenu with the parameter added.
#### Other distribution
Refer to your distribution's documentation
or contribute to this project to add a paragraph.
Refer to your distribution's documentation or contribute to this project to add a paragraph.
#

288
manpages/grub-btrfs.8.man Normal file
View File

@@ -0,0 +1,288 @@
.TH "grub-btrfs" "8"
.SH "NAME"
.PP
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
.SH "SYNOPSIS"
.PP
\fC/etc/grub.d/41_snapshots\-btrfs [\-V, \-\-version]\fP
.SH "DESCRIPTION"
.PP
Improves grub by adding “btrfs snapshots” to the grub menu.
.PP
You can boot your system on a “snapshot” from the grub menu.
Supports manual snapshots, snapper and timeshift.
Features of grub-btrfs:
.IP \(em 4
Automatically list snapshots existing on root partition (btrfs).
.IP \(em 4
Automatically detect if /boot is in separate partition.
.IP \(em 4
Automatically detect kernel, initramfs and intel/amd microcode in /boot directory on snapshots.
.IP \(em 4
Automatically create corresponding “menuentry” in grub.cfg
.IP \(em 4
Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
.IP \(em 4
Automatically generate grub.cfg if you use the provided systemd service.
.SH "CONFIGURATION"
.PP
grub-btrfs is configured via the file \fC/etc/default/grub\-btrfs/config\fP.
Possible options are:
.SS "GENERAL"
.SS "\fCGRUB_BTRFS_DISABLE\fP"
.PP
Disable grub-btrfs if true.
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_DISABLE="true"\fP
.SS "\fCGRUB_BTRFS_TITLE_FORMAT\fP"
.PP
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
.IP \(em 4
Default: (“date” “snapshot” “type” “description”)
.IP \(em 4
Example: \fCGRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")\fP
.SS "\fCGRUB_BTRFS_LIMIT\fP"
.PP
Maximum number of snapshots in the GRUB snapshots sub menu.
.IP \(em 4
Default: “50”
.IP \(em 4
Example: \fCGRUB_BTRFS_LIMIT="50"\fP
.SS "\fCGRUB_BTRFS_SUBVOLUME_SORT\fP"
.PP
Sort the found subvolumes by “ogeneration” or “generation” or “path” or “rootid”.
.IP \(em 4
See Sorting section in
.BR btrfs-subvolume (8)
.PP
“-rootid” means list snapshot by new ones first.
.IP \(em 4
Default: “-rootid”
.IP \(em 4
Example: \fCGRUB_BTRFS_SUBVOLUME_SORT="+ogen,\-gen,path,rootid"\fP
.SS "\fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND\fP"
.PP
Show snapshots found during run “grub-mkconfig”
.IP \(em 4
Default: “true”
.IP \(em 4
Example: \fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"\fP
.SS "\fCGRUB_BTRFS_ROOTFLAGS\fP"
.PP
Comma separated 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.
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"\fP
.SS "\fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION\fP"
.PP
By default “grub-btrfs” automatically detects your boot partition,
either located at the system root or on a separate partition or in a subvolume,
Change to “true” if your boot partition is not detected as separate.
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"\fP
.SS "\GRUB_BTRFS_ENABLE_CRYPTODISK\fP"
.PP
Enable booting from snapshots stored on LUKS encrypted devices
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \GRUB_BTRFS_ENABLE_CRYPTODISK="true"\fP
.SS "CUSTOM KERNELS"
.SS "\fCGRUB_BTRFS_NKERNEL\fP / \fCGRUB_BTRFS_NINIT\fP / \fCGRUB_BTRFS_CUSTOM_MICROCODE\fP"
.PP
By default, “grub-btrfs” automatically detects most existing kernels, initramfs and microcode.
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_NKERNEL=("kernel\-5.19.4\-custom" "vmlinux\-5.19.4\-custom")\fP
\fCGRUB_BTRFS_NINIT=("initramfs\-5.19.4\-custom.img" "initrd\-5.19.4\-custom.img" "otherinit\-5.19.4\-custom.gz")\fP
\fCGRUB_BTRFS_CUSTOM_MICROCODE=("custom\-ucode.img" "custom\-uc.img "custom_ucode.cpio")\fP
.SS "\fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS\fP"
.PP
Additional kernel command line parameters that should be passed to the kernelwhen
booting a snapshot.
For dracut based distros this could be useful to pass “rd.live.overlay.overlayfs=1”
or “rd.live.overlay.readonly=1” to the Kernel for booting read only snapshots.
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"\fP
.SS "SNAPSHOT FILTERING"
.SS "\fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH\fP"
.PP
Ignore specific path during run “grub-mkconfig”.
Only exact paths are ignored.
e.g : if `specific path` = @, only `@` snapshot will be ignored.
.IP \(em 4
Default: (“@”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")\fP
.SS "\fCGRUB_BTRFS_IGNORE_PREFIX_PATH\fP"
.PP
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.
.IP \(em 4
Default: (“var/lib/docker” “@var/lib/docker” “@/var/lib/docker”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")\fP
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE\fP"
.PP
Ignore specific type/tag of snapshot during run “grub-mkconfig”.
For snapper:
Type = single, pre, post.
For Timeshift:
Tag = boot, ondemand, hourly, daily, weekly, monthly.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")\fP
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION\fP"
.PP
Ignore specific description of snapshot during run “grub-mkconfig”.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")\fP
.SS "DISTRIBUTION DEPENDENT SETTINGS"
.SS "\fCGRUB_BTRFS_BOOT_DIRNAME\fP"
.PP
Location of kernels/initramfs/microcode.
Used by “grub-btrfs” to detect the boot partition and the location of kernels, initramfs and microcodes.
.IP \(em 4
Default: “/boot”
.IP \(em 4
Example: \fCGRUB_BTRFS_BOOT_DIRNAME="/"\fP
.SS "\fCGRUB_BTRFS_GRUB_DIRNAME\fP"
.PP
Location of the folder containing the “grub.cfg” file.
Might be grub2 on some systems.
For example, on Fedora with EFI : “/boot/efi/EFI/fedora”
.IP \(em 4
Default: “/boot/grub”
.IP \(em 4
Example: \fCGRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"\fP
.SS "\fCGRUB_BTRFS_GBTRFS_DIRNAME\fP"
.PP
Location where grub-btrfs.cfg should be saved.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
.IP \(em 4
Default: \fC$GRUB_BTRFS_GRUB_DIRNAME\fP
.IP \(em 4
Example: \fCGRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"\fP
.SS "\fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME\fP"
.PP
Location of the directory where Grub searches for the grub-btrfs.cfg file.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
.IP \(em 4
Default: “\${prefix}” (This is a grub variable that resolves to where grub is
.PP
installed. (like /boot/grub, /boot/efi/grub))
.IP \(em 4
NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
.PP
with `$\` before the `$`
.IP \(em 4
Example: \fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"\fP
.SS "\fCGRUB_BTRFS_MKCONFIG\fP"
.PP
Name/path of the command to generate the grub menu, used by “grub-btrfs.service”
Might be grub2-mkconfig on some systems (e.g. Fedora)
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
You can use the name of the command only or full the path.
.IP \(em 4
Default: grub-mkconfig
.IP \(em 4
Example: \fCGRUB_BTRFS_MKCONFIG=/sbin/grub2\-mkconfig\fP
.SS "\fCGRUB_BTRFS_SCRIPT_CHECK\fP"
.PP
Name of grub-script-check command, used by “grub-btrfs”
Might be grub2-script-check on some systems (e.g. Fedora)
.IP \(em 4
Default: grub-script-check
.IP \(em 4
Example: \fCGRUB_BTRFS_SCRIPT_CHECK=grub2\-script\-check\fP
.SS "\fCGRUB_BTRFS_MKCONFIG_LIB\fP"
.PP
Path of grub-mkconfig\d\s-2lib\s+2\u file, used by “grub-btrfs”
Might be /usr/share/grub2/grub-mkconfig\d\s-2lib\s+2\u on some systems (e.g. Opensuse)
.IP \(em 4
Default: /usr/share/grub/grub-mkconfig\d\s-2lib\s+2\u
.IP \(em 4
Example: \fCGRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub\-mkconfig_lib\fP
.SS "SECURITY"
.SS "\fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS\fP"
.PP
Password protection management for submenu, snapshots
Refer to the Grub documentation \fIhttps://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation\fP
and this comment \fIhttps://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660\fP
Add authorized usernames separate by comma (userfoo,userbar).
When Grubs password protection is enabled, the superuser is authorized by default, it is not necessary to add it
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"\fP
.SS "\fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU\fP"
.PP
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
does not work if GRUB\d\s-2BTRFS\s+2\u\d\s-2PROTECTION\s+2\u\d\s-2AUTHORIZED\s+2\u\d\s-2USERS\s+2\u is not empty
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"\fP
.SH "FILES"
.PP
/etc/default/grub-btrfs/config
.SH "SEE ALSO"
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
.SH "COPYRIGHT"
.PP
Copyright (c) 2022 Pascal Jäger

215
manpages/grub-btrfs.8.org Normal file
View File

@@ -0,0 +1,215 @@
#+title: grub-btrfs
#+author: Pascal Jaeger
#+MAN_CLASS_OPTIONS: :section-id "8"
* NAME
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
* SYNOPSIS
~/etc/grub.d/41_snapshots-btrfs [-V, --version]~
* DESCRIPTION
Improves grub by adding "btrfs snapshots" to the grub menu.
You can boot your system on a "snapshot" from the grub menu.
Supports manual snapshots, snapper and timeshift.
Features of grub-btrfs:
- 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 the type/tags and descriptions/comments of snapper/timeshift snapshots.
- Automatically generate grub.cfg if you use the provided systemd service.
* CONFIGURATION
grub-btrfs is configured via the file ~/etc/default/grub-btrfs/config~.
Possible options are:
** GENERAL
*** ~GRUB_BTRFS_DISABLE~
Disable grub-btrfs if true.
- Default: "false"
- Example: ~GRUB_BTRFS_DISABLE="true"~
*** ~GRUB_BTRFS_TITLE_FORMAT~
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
- Default: ("date" "snapshot" "type" "description")
- Example: ~GRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")~
*** ~GRUB_BTRFS_LIMIT~
Maximum number of snapshots in the GRUB snapshots sub menu.
- Default: "50"
- Example: ~GRUB_BTRFS_LIMIT="50"~
*** ~GRUB_BTRFS_SUBVOLUME_SORT~
Sort the found subvolumes by "ogeneration" or "generation" or "path" or "rootid".
- See Sorting section in
#+BEGIN_MAN
.BR btrfs-subvolume (8)
#+END_MAN
"-rootid" means list snapshot by new ones first.
- Default: "-rootid"
- Example: ~GRUB_BTRFS_SUBVOLUME_SORT="+ogen,-gen,path,rootid"~
*** ~GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND~
Show snapshots found during run "grub-mkconfig"
- Default: "true"
- Example: ~GRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"~
*** ~GRUB_BTRFS_ROOTFLAGS~
Comma separated 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: ""
- Example: ~GRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"~
*** ~GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION~
By default "grub-btrfs" automatically detects your boot partition,
either located at the system root or on a separate partition or in a subvolume,
Change to "true" if your boot partition is not detected as separate.
- Default: "false"
- Example: ~GRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"~
*** ~GRUB_BTRFS_ENABLE_CRYPTODISK~
Enable booting from snapshots stored on LUKS encrypted devices
- Default: "false"
- Example: ~GRUB_BTRFS_ENABLE_CRYPTODISK="true"~
** CUSTOM KERNELS
*** ~GRUB_BTRFS_NKERNEL~ / ~GRUB_BTRFS_NINIT~ / ~GRUB_BTRFS_CUSTOM_MICROCODE~
By default, "grub-btrfs" automatically detects most existing kernels, initramfs and microcode.
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
- Default: ("")
- Example: ~GRUB_BTRFS_NKERNEL=("kernel-5.19.4-custom" "vmlinux-5.19.4-custom")~
~GRUB_BTRFS_NINIT=("initramfs-5.19.4-custom.img" "initrd-5.19.4-custom.img" "otherinit-5.19.4-custom.gz")~
~GRUB_BTRFS_CUSTOM_MICROCODE=("custom-ucode.img" "custom-uc.img "custom_ucode.cpio")~
*** ~GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS~
Additional kernel command line parameters that should be passed to the kernelwhen
booting a snapshot.
For dracut based distros this could be useful to pass "rd.live.overlay.overlayfs=1"
or "rd.live.overlay.readonly=1" to the Kernel for booting read only snapshots.
- Default: ""
- Example: ~GRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"~
** SNAPSHOT FILTERING
*** ~GRUB_BTRFS_IGNORE_SPECIFIC_PATH~
Ignore specific path during run "grub-mkconfig".
Only exact paths are ignored.
e.g : if `specific path` = @, only `@` snapshot will be ignored.
- Default: ("@")
- Example: ~GRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")~
*** ~GRUB_BTRFS_IGNORE_PREFIX_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")
- Example: ~GRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")~
*** ~GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE~
Ignore specific type/tag of snapshot during run "grub-mkconfig".
For snapper:
Type = single, pre, post.
For Timeshift:
Tag = boot, ondemand, hourly, daily, weekly, monthly.
- Default: ("")
- Example: ~GRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")~
*** ~GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION~
Ignore specific description of snapshot during run "grub-mkconfig".
- Default: ("")
- Example: ~GRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")~
** DISTRIBUTION DEPENDENT SETTINGS
*** ~GRUB_BTRFS_BOOT_DIRNAME~
Location of kernels/initramfs/microcode.
Used by "grub-btrfs" to detect the boot partition and the location of kernels, initramfs and microcodes.
- Default: "/boot"
- Example: ~GRUB_BTRFS_BOOT_DIRNAME="/"~
*** ~GRUB_BTRFS_GRUB_DIRNAME~
Location of the folder containing the "grub.cfg" file.
Might be grub2 on some systems.
For example, on Fedora with EFI : "/boot/efi/EFI/fedora"
- Default: "/boot/grub"
- Example: ~GRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"~
*** ~GRUB_BTRFS_GBTRFS_DIRNAME~
Location where grub-btrfs.cfg should be saved.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
- Default: ~$GRUB_BTRFS_GRUB_DIRNAME~
- Example: ~GRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"~
*** ~GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME~
Location of the directory where Grub searches for the grub-btrfs.cfg file.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
- Default: "\${prefix}" (This is a grub variable that resolves to where grub is
installed. (like /boot/grub, /boot/efi/grub))
- NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
with `\` before the `$`
- Example: ~GRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"~
*** ~GRUB_BTRFS_MKCONFIG~
Name/path of the command to generate the grub menu, used by
#+BEGIN_MAN
.BR grub-btrfsd (8)
#+END_MAN
Might be 'grub2-mkconfig' on some systems (e.g. Fedora)
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
You can use the name of the command only or full the path.
- Default: grub-mkconfig
- Example: ~GRUB_BTRFS_MKCONFIG=/sbin/grub2-mkconfig~
*** ~GRUB_BTRFS_SCRIPT_CHECK~
Name of grub-script-check command, used by "grub-btrfs"
Might be 'grub2-script-check' on some systems (e.g. Fedora)
- Default: grub-script-check
- Example: ~GRUB_BTRFS_SCRIPT_CHECK=grub2-script-check~
*** ~GRUB_BTRFS_MKCONFIG_LIB~
Path of grub-mkconfig_lib file, used by "grub-btrfs"
Might be '/usr/share/grub2/grub-mkconfig_lib' on some systems (e.g. Opensuse)
- Default: /usr/share/grub/grub-mkconfig_lib
- Example: ~GRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub-mkconfig_lib~
** SECURITY
*** ~GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS~
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 (userfoo,userbar).
When Grub's password protection is enabled, the superuser is authorized by default, it is not necessary to add it
- Default: ""
- Example: ~GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"~
*** ~GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU~
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
does not work if GRUB_BTRFS_PROTECTION_AUTHORIZED_USERS is not empty
- Default: "false"
- Example: ~GRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"~
* FILES
/etc/default/grub-btrfs/config
* SEE ALSO
#+BEGIN_MAN
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
#+END_MAN
* COPYRIGHT
Copyright (c) 2022 Pascal Jäger

View File

@@ -0,0 +1,84 @@
.TH "grub-btrfsd" "8"
.SH "NAME"
.PP
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
.BR grub-btrfs (8)
.PP
when a new btrfs snapshot is created.
.SH "SYNOPSIS"
.PP
\fCgrub\-btrfsd [\-h, \-\-help] [\-c, \-\-no\-color] [\-l, \-\-log\-file LOG_FILE] [\-r, \-\-recursive] [\-s, \-\-syslog] [\-t, \-\-timeshift\-auto] [\-o, \-\-timeshift\-old] [\-v, \-\-verbose] SNAPSHOTS_DIRS\fP
.SH "DESCRIPTION"
.PP
Grub-btrfsd is a shell script which is meant to be run as a daemon.
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or \fC/etc/grub.d/41_snapshots\-btrfs\fP (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
.SH "OPTIONS"
.SS "\fCSNAPSHOTS_DIRS\fP"
.PP
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
E.g. for Snapper this would be \fC/.snapshots\fP. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
This argument is not necessary to provide if \fC\-\-timeshift\-auto\fP is set.
.SS "\fC\-c / \-\-no\-color\fP"
.PP
Disable colors in output.
.SS "\fC\-l / \-\-log\-file\fP"
.PP
This arguments specifies a file where grub-btrfsd should write log messages.
.SS "\fC\-r / \-\-recursive\fP"
.PP
Watch snapshot directory recursively
.SS "\fC\-s / \-\-syslog\fP"
.PP
Write to syslog
.SS "\fC\-t / \-\-timeshift\-auto\fP"
.PP
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. Where \fC$PID\fP is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument \fCSNAPSHOTS_DIRS\fP has no effect.
.SS "\fC\-o / \-\-timeshift\-old\fP"
.PP
Look for snapshots in \fC/run/timeshift/backup/timeshift\-btrfs\fP instead of \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. This is to be used for Timeshift versions <22.06.
.SS "\fC\-v / \-\-verbose\fP"
.PP
Let the log of the daemon be more verbose
.SS "\fC\-h / \-\-help\fP"
.PP
Displays a short help message.
.SH "CONFIGURATION"
.PP
The daemon is usually configured via the file \fC/etc/conf.d/grub\-btrfsd\fP on openrc-init systems and \fCsudo systemctl edit \-\-full grub\-btrfsd\fP on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
.SS "NOTES"
.PP
A common configuration for Snapper would be to set \fCSNAPSHOTS_DIR\fP to \fC/.snapshots\fP and not to set \fC\-\-timeshift\-auto\fP.
For Timeshift \fC\-\-timeshift\-auto\fP is set to true and \fCSNAPSHOTS_DIR\fP can be left as is.
.SH "FILES"
.PP
\fC/etc/conf.d/grub\-btrfsd\fP
\fC/usr/lib/systemd/system/grub\-btrfsd.service\fP
.SH "SEE ALSO"
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
.IR inotifywait (1)
.IR openrc (8)
.IR rc-service (8)
.IR timeshift (1)
.SH "COPYRIGHT"
.PP
Copyright (c) 2022 Pascal Jäger

View File

@@ -0,0 +1,73 @@
#+title: grub-btrfsd
#+author: Pascal Jaeger
#+MAN_CLASS_OPTIONS: :section-id "8"
* NAME
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
#+BEGIN_MAN
.BR grub-btrfs (8)
#+END_MAN
when a new btrfs snapshot is created.
* SYNOPSIS
~grub-btrfsd [-h, --help] [-c, --no-color] [-l, --log-file LOG_FILE] [-r, --recursive] [-s, --syslog] [-t, --timeshift-auto] [-o, --timeshift-old] [-v, --verbose] SNAPSHOTS_DIRS~
* DESCRIPTION
Grub-btrfsd is a shell script which is meant to be run as a daemon.
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or ~/etc/grub.d/41_snapshots-btrfs~ (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
* OPTIONS
** ~SNAPSHOTS_DIRS~
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
E.g. for Snapper this would be ~/.snapshots~. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
This argument is not necessary to provide if ~--timeshift-auto~ is set.
** ~-c / --no-color~
Disable colors in output.
** ~-l / --log-file~
This arguments specifies a file where grub-btrfsd should write log messages.
** ~-r / --recursive~
Watch snapshot directory recursively
** ~-s / --syslog~
Write to syslog
** ~-t / --timeshift-auto~
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to ~/run/timeshift/$PID/backup/timeshift-btrfs~. Where ~$PID~ is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument ~SNAPSHOTS_DIRS~ has no effect.
** ~-o / --timeshift-old~
Look for snapshots in ~/run/timeshift/backup/timeshift-btrfs~ instead of ~/run/timeshift/$PID/backup/timeshift-btrfs~. This is to be used for Timeshift versions <22.06.
** ~-v / --verbose~
Let the log of the daemon be more verbose
** ~-h / --help~
Displays a short help message.
* CONFIGURATION
The daemon is usually configured via the file ~/etc/conf.d/grub-btrfsd~ on openrc-init systems and ~sudo systemctl edit --full grub-btrfsd~ on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
** NOTES
A common configuration for Snapper would be to set ~SNAPSHOTS_DIR~ to ~/.snapshots~ and not to set ~--timeshift-auto~.
For Timeshift ~--timeshift-auto~ is set to true and ~SNAPSHOTS_DIR~ can be left as is.
* FILES
~/etc/conf.d/grub-btrfsd~
~/usr/lib/systemd/system/grub-btrfsd.service~
* SEE ALSO
#+BEGIN_MAN
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
.IR inotifywait (1)
.IR openrc (8)
.IR rc-service (8)
.IR timeshift (1)
#+END_MAN
* COPYRIGHT
Copyright (c) 2022 Pascal Jäger

280
temp/grub-btrfs.8 Normal file
View File

@@ -0,0 +1,280 @@
.TH "grub-btrfs" "8"
.SH "NAME"
.PP
grub-btrfs - Automatically add btrfs-Snapshots as a Grub submenu
.SH "SYNOPSIS"
.PP
\fC/etc/grub.d/41_snapshots\-btrfs [\-V, \-\-version]\fP
.SH "DESCRIPTION"
.PP
Improves grub by adding “btrfs snapshots” to the grub menu.
.PP
You can boot your system on a “snapshot” from the grub menu.
Supports manual snapshots, snapper and timeshift.
Features of grub-btrfs:
.IP \(em 4
Automatically list snapshots existing on root partition (btrfs).
.IP \(em 4
Automatically detect if /boot is in separate partition.
.IP \(em 4
Automatically detect kernel, initramfs and intel/amd microcode in /boot directory on snapshots.
.IP \(em 4
Automatically create corresponding “menuentry” in grub.cfg
.IP \(em 4
Automatically detect the type/tags and descriptions/comments of snapper/timeshift snapshots.
.IP \(em 4
Automatically generate grub.cfg if you use the provided systemd service.
.SH "CONFIGURATION"
.PP
grub-btrfs is configured via the file \fC/etc/default/grub\-btrfs/config\fP.
Possible options are:
.SS "GENERAL"
.SS "\fCGRUB_BTRFS_DISABLE\fP"
.PP
Disable grub-btrfs if true.
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_DISABLE="true"\fP
.SS "\fCGRUB_BTRFS_TITLE_FORMAT\fP"
.PP
The snapshot entries submenu in Grub are added according to this line. It is possible to change to order of the fields.
.IP \(em 4
Default: (“date” “snapshot” “type” “description”)
.IP \(em 4
Example: \fCGRUB_BTRFS_TITLE_FORMAT=("date" "snapshot" "type" "description")\fP
.SS "\fCGRUB_BTRFS_LIMIT\fP"
.PP
Maximum number of snapshots in the GRUB snapshots sub menu.
.IP \(em 4
Default: “50”
.IP \(em 4
Example: \fCGRUB_BTRFS_LIMIT="50"\fP
.SS "\fCGRUB_BTRFS_SUBVOLUME_SORT\fP"
.PP
Sort the found subvolumes by “ogeneration” or “generation” or “path” or “rootid”.
.IP \(em 4
See Sorting section in
.BR btrfs-subvolume (8)
.PP
“-rootid” means list snapshot by new ones first.
.IP \(em 4
Default: “-rootid”
.IP \(em 4
Example: \fCGRUB_BTRFS_SUBVOLUME_SORT="+ogen,\-gen,path,rootid"\fP
.SS "\fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND\fP"
.PP
Show snapshots found during run “grub-mkconfig”
.IP \(em 4
Default: “true”
.IP \(em 4
Example: \fCGRUB_BTRFS_SHOW_SNAPSHOTS_FOUND="false"\fP
.SS "\fCGRUB_BTRFS_ROOTFLAGS\fP"
.PP
Comma separated 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.
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_ROOTFLAGS="space_cache,commit=10,norecovery"\fP
.SS "\fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION\fP"
.PP
By default “grub-btrfs” automatically detects your boot partition,
either located at the system root or on a separate partition or in a subvolume,
Change to “true” if your boot partition is not detected as separate.
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_OVERRIDE_BOOT_PARTITION_DETECTION="true"\fP
.SS "CUSTOM KERNELS"
.SS "\fCGRUB_BTRFS_NKERNEL\fP / \fCGRUB_BTRFS_NINIT\fP / \fCGRUB_BTRFS_CUSTOM_MICROCODE\fP"
.PP
By default, “grub-btrfs” automatically detects most existing kernels, initramfs and microcode.
Customs kernel, initramfs and microcodes that are not detected can be added in these variables.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_NKERNEL=("kernel\-5.19.4\-custom" "vmlinux\-5.19.4\-custom")\fP
\fCGRUB_BTRFS_NINIT=("initramfs\-5.19.4\-custom.img" "initrd\-5.19.4\-custom.img" "otherinit\-5.19.4\-custom.gz")\fP
\fCGRUB_BTRFS_CUSTOM_MICROCODE=("custom\-ucode.img" "custom\-uc.img "custom_ucode.cpio")\fP
.SS "\fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS\fP"
.PP
Additional kernel command line parameters that should be passed to the kernelwhen
booting a snapshot.
For dracut based distros this could be useful to pass “rd.live.overlay.overlayfs=1”
or “rd.live.overlay.readonly=1” to the Kernel for booting read only snapshots.
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_SNAPSHOT_KERNEL_PARAMETERS="rd.live.overlay.overlayfs=1"\fP
.SS "SNAPSHOT FILTERING"
.SS "\fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH\fP"
.PP
Ignore specific path during run “grub-mkconfig”.
Only exact paths are ignored.
e.g : if `specific path` = @, only `@` snapshot will be ignored.
.IP \(em 4
Default: (“@”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SPECIFIC_PATH=("@home")\fP
.SS "\fCGRUB_BTRFS_IGNORE_PREFIX_PATH\fP"
.PP
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.
.IP \(em 4
Default: (“var/lib/docker” “@var/lib/docker” “@/var/lib/docker”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_PREFIX_PATH=("var/lib/docker" "@var/lib/docker" "@/var/lib/docker")\fP
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE\fP"
.PP
Ignore specific type/tag of snapshot during run “grub-mkconfig”.
For snapper:
Type = single, pre, post.
For Timeshift:
Tag = boot, ondemand, hourly, daily, weekly, monthly.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_TYPE=("ondemand")\fP
.SS "\fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION\fP"
.PP
Ignore specific description of snapshot during run “grub-mkconfig”.
.IP \(em 4
Default: (“”)
.IP \(em 4
Example: \fCGRUB_BTRFS_IGNORE_SNAPSHOT_DESCRIPTION=("timeline")\fP
.SS "DISTRIBUTION DEPENDENT SETTINGS"
.SS "\fCGRUB_BTRFS_BOOT_DIRNAME\fP"
.PP
Location of kernels/initramfs/microcode.
Used by “grub-btrfs” to detect the boot partition and the location of kernels, initramfs and microcodes.
.IP \(em 4
Default: “/boot”
.IP \(em 4
Example: \fCGRUB_BTRFS_BOOT_DIRNAME="/"\fP
.SS "\fCGRUB_BTRFS_GRUB_DIRNAME\fP"
.PP
Location of the folder containing the “grub.cfg” file.
Might be grub2 on some systems.
For example, on Fedora with EFI : “/boot/efi/EFI/fedora”
.IP \(em 4
Default: “/boot/grub”
.IP \(em 4
Example: \fCGRUB_BTRFS_GRUB_DIRNAME="/boot/grub2"\fP
.SS "\fCGRUB_BTRFS_GBTRFS_DIRNAME\fP"
.PP
Location where grub-btrfs.cfg should be saved.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
.IP \(em 4
Default: \fC$GRUB_BTRFS_GRUB_DIRNAME\fP
.IP \(em 4
Example: \fCGRUB_BTRFS_GBTRFS_DIRNAME="/.snapshots"\fP
.SS "\fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME\fP"
.PP
Location of the directory where Grub searches for the grub-btrfs.cfg file.
Some distributions (like OpenSuSE) store those file at the snapshot directory
instead of boot. Be aware that this directory must be available for grub during
startup of the system.
.IP \(em 4
Default: “\${prefix}” (This is a grub variable that resolves to where grub is
.PP
installed. (like /boot/grub, /boot/efi/grub))
.IP \(em 4
NOTE: If variables of grub are used here like ${prefix}, they need to be escaped
.PP
with `$\` before the `$`
.IP \(em 4
Example: \fCGRUB_BTRFS_GBTRFS_SEARCH_DIRNAME="\${prefix}"\fP
.SS "\fCGRUB_BTRFS_MKCONFIG\fP"
.PP
Name/path of the command to generate the grub menu, used by “grub-btrfs.service”
Might be grub2-mkconfig on some systems (e.g. Fedora)
Default paths are /sbin:/bin:/usr/sbin:/usr/bin, if your path is missing, report it on the upstream project.
You can use the name of the command only or full the path.
.IP \(em 4
Default: grub-mkconfig
.IP \(em 4
Example: \fCGRUB_BTRFS_MKCONFIG=/sbin/grub2\-mkconfig\fP
.SS "\fCGRUB_BTRFS_SCRIPT_CHECK\fP"
.PP
Name of grub-script-check command, used by “grub-btrfs”
Might be grub2-script-check on some systems (e.g. Fedora)
.IP \(em 4
Default: grub-script-check
.IP \(em 4
Example: \fCGRUB_BTRFS_SCRIPT_CHECK=grub2\-script\-check\fP
.SS "\fCGRUB_BTRFS_MKCONFIG_LIB\fP"
.PP
Path of grub-mkconfig\d\s-2lib\s+2\u file, used by “grub-btrfs”
Might be /usr/share/grub2/grub-mkconfig\d\s-2lib\s+2\u on some systems (e.g. Opensuse)
.IP \(em 4
Default: /usr/share/grub/grub-mkconfig\d\s-2lib\s+2\u
.IP \(em 4
Example: \fCGRUB_BTRFS_MKCONFIG_LIB=/usr/share/grub2/grub\-mkconfig_lib\fP
.SS "SECURITY"
.SS "\fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS\fP"
.PP
Password protection management for submenu, snapshots
Refer to the Grub documentation \fIhttps://www.gnu.org/software/grub/manual/grub/grub.html#Authentication-and-authorisation\fP
and this comment \fIhttps://github.com/Antynea/grub-btrfs/issues/95#issuecomment-682295660\fP
Add authorized usernames separate by comma (userfoo,userbar).
When Grubs password protection is enabled, the superuser is authorized by default, it is not necessary to add it
.IP \(em 4
Default: “”
.IP \(em 4
Example: \fCGRUB_BTRFS_PROTECTION_AUTHORIZED_USERS="userfoo,userbar"\fP
.SS "\fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU\fP"
.PP
Disable authentication support for submenu of Grub-btrfs only (--unrestricted)
does not work if GRUB\d\s-2BTRFS\s+2\u\d\s-2PROTECTION\s+2\u\d\s-2AUTHORIZED\s+2\u\d\s-2USERS\s+2\u is not empty
.IP \(em 4
Default: “false”
.IP \(em 4
Example: \fCGRUB_BTRFS_DISABLE_PROTECTION_SUBMENU="true"\fP
.SH "FILES"
.PP
/etc/default/grub-btrfs/config
.SH "SEE ALSO"
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
.SH "COPYRIGHT"
.PP
Copyright (c) 2022 Pascal Jäger

84
temp/grub-btrfsd.8 Normal file
View File

@@ -0,0 +1,84 @@
.TH "grub-btrfsd" "8"
.SH "NAME"
.PP
grub-btrfsd - An OpenRC daemon to automatically update the grub menu with
.BR grub-btrfs (8)
.PP
when a new btrfs snapshot is created.
.SH "SYNOPSIS"
.PP
\fCgrub\-btrfsd [\-h, \-\-help] [\-c, \-\-no\-color] [\-l, \-\-log\-file LOG_FILE] [\-r, \-\-recursive] [\-s, \-\-syslog] [\-t, \-\-timeshift\-auto] [\-o, \-\-timeshift\-old] [\-v, \-\-verbose] SNAPSHOTS_DIRS\fP
.SH "DESCRIPTION"
.PP
Grub-btrfsd is a shell script which is meant to be run as a daemon.
Grub-btrfsd watches a directory where btrfs-snapshots are created or deleted via inotifywait and runs grub-mkconfig (if grub-mkconfig never ran before since grub-btrfs was installed) or \fC/etc/grub.d/41_snapshots\-btrfs\fP (when grub-mkconfig ran before with grub-btrfs installed) when something in that directory changes.
.SH "OPTIONS"
.SS "\fCSNAPSHOTS_DIRS\fP"
.PP
This argument specifies the (space separated) paths where grub-btrfsd looks for newly created snapshots and snapshot deletions. It is usually defined by the program used to make snapshots.
E.g. for Snapper this would be \fC/.snapshots\fP. It is possible to define more than one directory here, all directories will inherit the same settings (recursive etc.).
This argument is not necessary to provide if \fC\-\-timeshift\-auto\fP is set.
.SS "\fC\-c / \-\-no\-color\fP"
.PP
Disable colors in output.
.SS "\fC\-l / \-\-log\-file\fP"
.PP
This arguments specifies a file where grub-btrfsd should write log messages.
.SS "\fC\-r / \-\-recursive\fP"
.PP
Watch snapshot directory recursively
.SS "\fC\-s / \-\-syslog\fP"
.PP
Write to syslog
.SS "\fC\-t / \-\-timeshift\-auto\fP"
.PP
This is a flag to activate the auto detection of the path where Timeshift stores snapshots. Newer versions (>=22.06) of Timeshift mount their snapshots to \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. Where \fC$PID\fP is the process ID of the currently running Timeshift session. The PID is changing every time Timeshift is opened. grub-btrfsd can automatically take care of the detection of the correct PID and directory if this flag is set. In this case the argument \fCSNAPSHOTS_DIRS\fP has no effect.
.SS "\fC\-o / \-\-timeshift\-old\fP"
.PP
Look for snapshots in \fC/run/timeshift/backup/timeshift\-btrfs\fP instead of \fC/run/timeshift/$PID/backup/timeshift\-btrfs\fP. This is to be used for Timeshift versions <22.06.
.SS "\fC\-v / \-\-verbose\fP"
.PP
Let the log of the daemon be more verbose
.SS "\fC\-h / \-\-help\fP"
.PP
Displays a short help message.
.SH "CONFIGURATION"
.PP
The daemon is usually configured via the file \fC/etc/conf.d/grub\-btrfsd\fP on openrc-init systems and \fCsudo systemctl edit \-\-full grub\-btrfsd\fP on systemd systems. In this file the arguments (See OPTIONS), that OpenRC passes to the daemon when it is started, can be configured.
.SS "NOTES"
.PP
A common configuration for Snapper would be to set \fCSNAPSHOTS_DIR\fP to \fC/.snapshots\fP and not to set \fC\-\-timeshift\-auto\fP.
For Timeshift \fC\-\-timeshift\-auto\fP is set to true and \fCSNAPSHOTS_DIR\fP can be left as is.
.SH "FILES"
.PP
\fC/etc/conf.d/grub\-btrfsd\fP
\fC/usr/lib/systemd/system/grub\-btrfsd.service\fP
.SH "SEE ALSO"
.IR btrfs (8)
.IR btrfs-subvolume (8)
.IR grub-btrfsd (8)
.IR grub-mkconfig (8)
.IR inotifywait (1)
.IR openrc (8)
.IR rc-service (8)
.IR timeshift (1)
.SH "COPYRIGHT"
.PP
Copyright (c) 2022 Pascal Jäger