5 # shows function args when: shopt -s extdebug
6 local -i argc_index
=0 arg frame i start
=${1:-1} max_indent
=8 indent
9 if [[ $
(shopt -p extdebug
) == *-s* ]]; then
13 for ((frame
=0; frame
< ${#FUNCNAME[@]}-1; frame
++)); do
14 argc
=${BASH_ARGC[frame]}
16 ((frame
< start
)) && continue
17 if (( ${#BASH_SOURCE[@]} > 1 )); then
18 source="${BASH_SOURCE[frame+1]}:${BASH_LINENO[frame]}:"
20 indent
=$
((frame-start
+1))
21 indent
=$
((indent
< max_indent ? indent
: max_indent
))
22 printf "%${indent}s↳%sin \`%s" '' "$source" "${FUNCNAME[frame]}"
24 for ((i
=argc_index-1
; i
>= argc_index-argc
; i--
)); do
25 printf " %s" "${BASH_ARGV[i]}"
34 set -E; shopt -s extdebug
38 echo "${BASH_SOURCE[1]}:${BASH_LINENO[0]}:in \`$BASH_COMMAND' returned $err"
40 echo "$0: exiting with code $err"
49 [[ $EUID == 0 ]] || sudo
"$BASH_SOURCE" "$@"
53 Usage: ${0##*/} [OPTIONS] +/-SIZE[g] swap|boot
55 Assuming Ian Kelling's partition scheme,
56 Resize swap or boot, expanding or shrinking the root fs and partition to compensate.
59 -r Reboot now if it's needed.
60 -h|--help Print help and exit.
62 SIZE is MiB, or if g is specified, GiB.
64 If using multiple devices, SIZE is applied to each device, so total change is
67 Note: Uses GNU getopt options parsing style
75 temp
=$
(getopt
-l opt o
"$@") || usage
1
79 -r) reboot_now
=true
; shift ;;
80 -n) dry_run
=true
; shift ;;
83 *) echo "$0: Internal error!" ; exit 1 ;;
87 #### begin arg error checking ####
89 if [[ $# != 2 ]]; then
90 echo "$0: error: expected 2 arguments"
94 if [[ $1 != [+-][0-9]* ]]; then
95 echo "$0: error: bad 1st arg: $1"
99 if ! which parted
&>/dev
/null
; then
100 echo "$0: error: install parted"
104 case $2 in swap|boot
) : ;; *) echo "$0: error: bad 2nd arg"; usage
1 ;; esac
106 #### end arg error checking ####
110 [[ $2 == boot
]] || boot
=false
112 op_size
=$1 # operator plus size
113 [[ $op_size != *g
]] || op_size
=$
(( ${op_size%g} / 1024 ))
116 if [[ $op_size == +* ]]; then
117 op_size_rev
=-$size # rev = reverse
125 ##### end command line parsing ########
131 reboot_script_initialized
=false
137 p mkpart primary
"$4" \
138 $
((${ptable[start$part]} $start_op)) $
((${ptable[end$part]} $end_op))
145 e
() { echo "+ $@"; "$@"; }
152 while read devid dev
; do
156 while IFS
=: read id start end psize _
; do
157 [[ $id == [0-9] ]] ||
continue
158 ptable
[start
$id]=start
=${start%%[^0-9]*}
159 ptable
[end
$id]=${end%%[^0-9]*}
160 ptable
[size
$id]=${psize%%[^0-9]*}
161 done < <(parted
-m /dev
/$dev unit MiB print
)
162 parted
/dev
/$dev unit MiB print |
tee /root
/backup_partition_table_
$dev
163 p
() { e parted
-a optimal
-s -- /dev
/$dev unit MiB
"$@"; }
164 e systemctl stop systemd-cryptsetup@crypt_swap_
$dev$swapn
165 sleep 1 # dunno if this is needed,
166 # but systemd likes to do these kind of things in the background.
168 # These partition comments seems a little verbose now, but I bet they
169 # will be helpfull if I read this in more than a week from now.
170 # <> = deleted partition, () = partition
171 p
rm $swapn # ( root )< swap >( boot )
173 root_resize_cmd
="e btrfs fi resize $devid:${op_size_rev}M /"
174 if $grow; then $root_resize_cmd; fi
176 # < root >< swap >( boot )
177 # ( root ) >< swap >( boot )
179 # < root >< swap >( boot )
180 # ( root >< ) swap >( boot )
182 out
=$
(p
rm $rootn 2>&1)
185 pmk
$rootn "" $op_size_rev
188 grep "but we have been unable to inform the kernel" &>/dev
/null
; then
192 if $needs_reboot; then
193 e systemctl mask dev-mapper-crypt_swap_
$dev$swapn.swap
194 e systemctl mask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
195 e
() { echo "$@" >> /root
/finish-resize
; }
196 if ! $reboot_script_initialized; then
197 reboot_script_initialized
=true
198 rm -rf /root
/finish-resize
199 cat >/root
/finish-resize
<<'EOF'
202 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
204 chmod +x
/root
/finish-resize
206 e systemctl unmask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
207 e systemctl unmask dev-mapper-crypt_swap_
$dev$swapn.swap
212 boot_devid
=$
(btrfs
fi show
/boot | \
213 sed -rn "s#^\s*devid\s+(\S+)\s.*$dev[0-9]#\1#p")
216 # shrink boot, move it to a temp file
217 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
219 temp_boot
=/root
/temp_boot_
$dev
220 e
dd bs
=1M
if=/dev
/$dev$bootn of
=$temp_boot \
221 count
=$
((${ptable[size$bootn]} $op_size))
226 # ( root ) >< swap >< boot >
227 # ( root )( >< swap ) >< boot >
228 # ( root )( >< swap )( >< boot )
230 # ( root >< ) swap >< boot >
231 # ( root >< )( swap >< ) boot >
232 # ( root >< )( swap >< )( boot )
234 pmk
$swapn $op_size_rev $op_size_rev "linux-swap"
235 pmk
$bootn $op_size_rev ""
238 e
dd bs
=1M
if=/dev
/$dev$bootn of
=/dev
/$dev$bootn skip
=$size
240 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
242 e
dd bs
=1M
if=$temp_boot of
=/dev
/$dev$bootn
246 # if $grow; then ( root )( >< swap )( boot )
247 # else ( root >< )( swap )( boot )
248 pmk
$swapn $op_size_rev "" "linux-swap"
249 e systemctl start systemd-cryptsetup@crypt_swap_
$dev$swapn
251 done < <(btrfs
fi show
/ | \
252 sed -nr 's#^\s*devid\s*(\S+)\s.*_([^_ ]+)[0-9]\s*$#\1 \2#p')
256 e
rm -rf "/root/temp_boot_*"
257 e
rm -f /root
/finish-resize
260 if $needs_reboot; then
262 echo "$0: Reboot, run /root/finish-resize. It's contents:"
263 cat /root
/finish-resize
265 echo "$0: If you want to resize again later, a reboot is required first."
268 echo "$0: rebooting now"