forked from Antynea/grub-btrfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path41_snapshots-btrfs
154 lines (145 loc) · 5.96 KB
/
41_snapshots-btrfs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#! /usr/bin/bash
#
#
#########################################################################################################################################
# Written by: Antynea #
# #
# Purpose: Include btrfs snapshots at boot options. #
# #
# What this script does: #
# - List snapshots existing on root partition (btrfs). #
# - Create corresponding menuentry in grub.cfg , which ensures a very easy rollback. #
# #
# How to use it: #
# - Add this lines to /etc/default/grub: #
# #
# * GRUB_BTRFS_SUBMENUNAME="ArchLinux Snapshots" (Name menu appearing in grub.) #
# * GRUB_BTRFS_PREFIXENTRY="Snapshot" (Add a name ahead your snapshots entries.) #
# * GRUB_BTRFS_NKERNEL=("vmlinuz-linux") (Custom Name kernel you use it.) #
# * GRUB_BTRFS_NINIT=("initramfs-linux.img" "initramfs-linux-fallback.img") (Custom Name initramfs (ramdisk) you use it.) #
# * GRUB_BTRFS_INTEL_UCODE=("intel-ucode.img") (Custom Name intel microcode you use it.) #
# #
# - Generate grub.cfg (on Archlinux use grub-mkconfig -o /boot/grub/grub.cfg ) #
# #
# - grub-btrfs automatically generates snapshots entries. #
# - You will see it appear different entries, e.g : Prefixentry name of snapshot [2013-02-11 04:00:00] #
# #
# Warning: #
# This version detect kernels,initramfs,intel microcode only in boot partition, not in snapshot. #
# If those that are present in boot partition but not in snapshot, #
# entry will be created but not fonctional, you don't boot it. #
# #
#########################################################################################################################################
set -e
. /usr/share/grub/grub-mkconfig_lib
. /etc/default/grub
######################################
### variables in /etc/default/grub ###
######################################
## Submenu name
submenuname=${GRUB_BTRFS_SUBMENUNAME:-"ArchLinux Snapshots"}
## Prefix entry
prefixentry=${GRUB_BTRFS_PREFIXENTRY:-"Snapshot"}
## Kernel(s) name(s)
nkernel=("${GRUB_BTRFS_NKERNEL[@]:-vmlinuz-linux}")
## Initramfs name(s)
ninit=("${GRUB_BTRFS_NINIT[@]:-initramfs-linux.img initramfs-linux-fallback.img}")
## Intel-ucode name(s)
intel_ucode=("${GRUB_BTRFS_INTEL_UCODE[@]:-intel-ucode.img}")
########################
### variables script ###
########################
## Internationalization (default : english)
export TEXTDOMAIN=grub-btrfs-git
export TEXTDOMAINDIR="/usr/share/locale"
## hints string
pboot=$(${grub_probe} --target="hints_string" "/boot" 2>/dev/null)
## UUID of the root partition
uuid=$(${grub_probe} "/" --target="fs_uuid" 2>/dev/null)
## UUID of the boot partition
buuid=$(${grub_probe} --target="fs_uuid" "/boot" 2>/dev/null)
## Parameters passed to the kernel
params="$GRUB_CMDLINE_LINUX $GRUB_CMDLINE_LINUX_DEFAULT"
##############
### Script ###
##############
typeset -A date_time
unset snapshots
# Create list of filesystem snapshots
oldIFS=$IFS
IFS=$'\n'
for snap in $($bindir/btrfs subvolume list -sa / --sort=-ogen | $bindir/awk '{gsub(/^.*<FS_TREE>\//,"",$NF);print $11" "$12"?"$NF}'); do
snap_name="${snap#*"?"}"
# Discard deleted snapshots
if [ $snap_name = "DELETED" ]; then continue; fi
snapshots+=("$snap_name")
date_time[$snap_name]="${snap%"?"*}"
done
IFS=$oldIFS
# Display the menu
echo "submenu '$submenuname' {"
# Treat the kernel variables (Translation unclear)
for kernel in ${nkernel[@]}; do
# Check the specified kernel(s) exist, if it/they don't, display an error and exit
if [ ! -f /boot/$kernel ]; then gettext_printf $"Error: /boot/$kernel, kernel does not exist" >&2; exit 1; fi
# If there are >1 kernels, create a menu
if [ ${#nkernel[*]} != 1 ]; then echo " submenu '$kernel' {
submenu '---> Kernel: $kernel <---' { echo }"; fi
# Treat the snapshots variable
for item in ${snapshots[@]}; do
# Output name of snapshot
gettext_printf $"Found Snapshot: %s\n" "$item ${date_time[$item]}" >&2
# Create a menu for remaining snapshots (name + creation date)
echo " submenu '$prefixentry $item [${date_time[$item]}]' {"
# if more than one kernel is found, create a menu
if [ ${#nkernel[*]} != 1 ]; then echo " submenu '---> Kernel: $kernel <---' { echo }"; fi
# Treat the initramfs variable
for init in ${ninit[@]}; do
# Check the specified initramfs(es) exist, if it/they don't, display an error and exit
if [ ! -f /boot/$init ]; then gettext_printf $"Error: /boot/$init, initramfs does not exist" >&2; exit 1; fi
# Specify a kernel and initramfs for every snapshot
echo "\
menuentry '$item $init' --class arch --class gnu-linux --class gnu --class os "\$menuentry_id_option" 'gnulinux-snapshots-$uuid'{
load_video
set gfxpayload=$GRUB_GFXPAYLOAD_LINUX
if [ x"\$feature_platform_search_hint" = xy ]; then
search --no-floppy --fs-uuid --set=root $pboot $buuid
else
search --no-floppy --fs-uuid --set=root $buuid
fi
echo 'Loading Linux snapshot ...'"
# Check the location of the /boot partition
if [ $uuid = $buuid ]; then
echo "\
linux /$item/boot/$kernel root=UUID=$uuid rw rootflags=subvol=$item $params
echo 'Loading initial ramdisk ...'"
# Check intel microcode exist
if [ -f /boot/$intel_ucode ]; then
echo "\
initrd /$item/boot/$intel_ucode /$item/boot/$init"
else
echo "\
initrd /$item/boot/$init"
fi
else
echo "\
linux /$kernel root=UUID=$uuid rw rootflags=subvol=$item $params
echo 'Loading initial ramdisk ...'"
# Check intel microcode exist
if [ -f /boot/$intel_ucode ]; then
echo "\
initrd /$intel_ucode /$init"
else
echo "\
initrd /$init"
fi
fi
echo "\
}"
done
echo " }"
done
# Don't forget to close menus if more than one kernel is found
if [ ${#nkernel[*]} != 1 ]; then echo " }"; fi
done
echo "}"