-
Notifications
You must be signed in to change notification settings - Fork 49
/
init.d_autoexpand_root-4
196 lines (189 loc) · 7.17 KB
/
init.d_autoexpand_root-4
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/sbin/openrc-run
#
# Automatically attempt to extend root partition (calculated from
# the root=... kernel command line parameter, with root=PARTUUID=... allowed)
# to fill remaining free space on the card
#
# Operates on a live root filesystem: first pass will simply expand the
# partition, then reboot (as it is not possible to change the kernel partition
# table entry for / on a running system); on the second pass, we resize the
# root filesystem (this can be done 'live'), then add xdm to the default
# runlevel, and start it (to bring up the Xfce4 demouser session).
#
# Checks for a sentinel file "autoexpand_root_partition" on /boot (the
# microSD card's first partition), and will proceed only if found. On first
# run, it is replaced with the file "autoexpand_root_filesystem" (and on
# second run, this latter sentinel file is deleted).
#
# On first run, the root and demouser password will also be set, to
# "raspberrypi64"; if you _only_ want to do this (and not extend the root
# partition) then create an "autoexpand_root_none" sentinel file on /boot (in
# place of "autoexpand_root_partition"). For avoidance of doubt, doing so
# will still enable Xfce4, and start the demouser session.
#
# Copyright (c) 2017 sakaki <[email protected]>
# License: GPL 3.0+
# NO WARRANTY
description="Auto-expands root partition and sets passwords (for gentoo-on-rpi3-64bit)"
depend() {
need localmount
after modules sysctl root
}
SENTINEL1="/boot/autoexpand_root_partition"
SENTINEL2="/boot/autoexpand_root_filesystem"
SENTINEL3="/boot/autoexpand_root_none"
DEFAULTPW="raspberrypi64"
_resize_if_necessary() {
local PUUID="" KROOTPART="" ROOTDRIVE="" ROOTPART="" PNUM=""
if [[ -f "${SENTINEL1}" || -f "${SENTINEL2}" ]]; then
# begin by finding the specified root from the kernel command line
KROOTPART="$(awk -v RS=" " '/^root=/ {print substr($0,6)}' /proc/cmdline)"
if [[ -z "${KROOTPART}" ]]; then
eerror "Could not find root=<...> term in kernel command line"
return 1
fi
# if a PARTUUID spec, look it up
if grep -q "PARTUUID=" <<<"${KROOTPART}"; then
PUUID="$(cut -d '=' -f 2 <<<"${KROOTPART}" )"
# make sure lower case
PUUID="${PUUID,,}"
if ! ROOTPART="$(findfs PARTUUID=${PUUID})"; then
eerror "Failed to locate root on PARTUUID ${PUUID}"
return 1
fi
else
# otherwise, just take it as is
ROOTPART="${KROOTPART}"
fi
# extract the drive from the partition name, e.g.
# /dev/sda2 -> /dev/sda
# /dev/mmcblk0p2 -> /dev/mmcblk0
ROOTDRIVE="$(sed 's/[0-9]*$//;s/\([0-9]\)p$/\1/' <<<"${ROOTPART}")"
# get the partition number too
PNUM="$(egrep -o "[0-9]+$" <<<"${ROOTPART}")"
if [[ -z "${ROOTPART}" || -z "${ROOTDRIVE}" || -z "${PNUM}" ]]; then
eerror "Unable to determine root path components"
return 1
fi
fi
if [ -f "${SENTINEL1}" ]; then
# first boot, need to resize root partition to fill disk
# then, since this is /, need to reboot to get kernel to see it
# after which its ext4 filesystem can be resized online
ewarn ""
ewarn "*******************************************************************"
ewarn "* Auto resizing root partition to fill microSD card - please wait *"
ewarn "* (we will reboot immediately this is done, so kernel notices) *"
ewarn "*******************************************************************"
ewarn ""
rm -f "${SENTINEL1}"
if [ -f "${SENTINEL1}" ]; then
# might mean an ro filesystem, and we don't want an
# infinite loop
eerror "Failed to delete sentinel file '${SENTINEL1}'"
return 1
fi
# turn off swapfiles, for safety
swapoff -a
# sync filesystems before we begin, to minimize any damage if things
# should go wrong
sync
# begin by resizing the root partition
if ! sfdisk --no-reread --no-tell-kernel -N ${PNUM} <<<", +" "${ROOTDRIVE}" &>/dev/null; then
eerror "Failed to resize root partition"
return 1
fi
# create second sentinel to mark that we have done this
touch "${SENTINEL2}"
if ! [ -f "${SENTINEL2}" ]; then
eerror "Failed to create sentinel file '${SENTINEL2}'"
return 1
fi
# now, change passwords
ewarn "Changing root and demouser passwords, to '${DEFAULTPW}'"
chpasswd <<<"root:${DEFAULTPW}" &>/dev/null
chpasswd <<<"demouser:${DEFAULTPW}" &>/dev/null
ewarn ""
ewarn "*******************************************************************"
ewarn "* Resize completed - rebooting now (this will only happen once) *"
ewarn "*******************************************************************"
ewarn ""
# let the user read it
sleep 5
# then reboot, but don't do it in the context of this, an init script
sync
nohup bash -c 'reboot' &>/dev/null&
elif [ -f "${SENTINEL2}" ]; then
# second boot, partition has been resized (and kernel is aware); so now
# we just need to update the filesystem, which can be done online
ewarn ""
ewarn "*******************************************************************"
ewarn "* Auto resizing root filesystem to fill partition ${PNUM} - please wait *"
ewarn "*******************************************************************"
ewarn ""
rm -f "${SENTINEL2}"
if [ -f "${SENTINEL2}" ]; then
eerror "Failed to delete sentinel file '${SENTINEL2}'"
return 1
fi
# turn off swapfiles, for safety
swapoff -a
# sync filesystems before we begin, to minimize any damage if things
# should go wrong
sync
# do an online resize of the root partition's ext4 filing system
if ! resize2fs -f "${ROOTPART}" &>/dev/null; then
eerror "Failed to resize root filesystem"
return 1
fi
# restore swaps
swapon -a
ewarn ""
ewarn "*******************************************************************"
ewarn "* Root filesystem resized OK - proceeding with boot! *"
ewarn "*******************************************************************"
ewarn ""
# let the user read it
sleep 5
# then ensure we don't run again, and that graphical login
# starts up (disabled by default on the image)
sync
rc-update del "${SVCNAME}" boot &>/dev/null
rc-update add xdm default &>/dev/null
rc-update --update &>/dev/null
elif [ -f "${SENTINEL3}" ]; then
# First boot, with no resizing requested.
# we just need to update the passwords and logon
rm -f "${SENTINEL3}"
if [ -f "${SENTINEL3}" ]; then
eerror "Failed to delete sentinel file '${SENTINEL3}'"
return 1
fi
# Change passwords
ewarn "Changing root and demouser passwords, to '${DEFAULTPW}'"
chpasswd <<<"root:${DEFAULTPW}" &>/dev/null
chpasswd <<<"demouser:${DEFAULTPW}" &>/dev/null
ewarn ""
ewarn "*******************************************************************"
ewarn "* Changed passwords - proceeding with boot! *"
ewarn "*******************************************************************"
ewarn ""
# let the user read it
sleep 5
# then ensure we don't run again, and that graphical login
# starts up (disabled by default on the image)
sync
rc-update del "${SVCNAME}" boot &>/dev/null
rc-update add xdm default &>/dev/null
rc-update --update &>/dev/null
else
# no sentinel found, service should really be disabled
ewarn "No sentinel detected; consider deleting ${SVCNAME} from boot runlevel"
fi
return 0
}
start() {
ebegin "Starting ${SVCNAME}"
_resize_if_necessary
eend $?
}