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##*/} [-n] +/-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.
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
76 -r) reboot_now
=true
; shift ;;
77 -n) dry_run
=true
; shift ;;
83 #### begin arg error checking ####
85 if [[ $# != 2 ]]; then
86 echo "$0: error: expected 2 arguments"
90 if [[ $1 != [+-][0-9]* ]]; then
91 echo "$0: error: bad 1st arg: $1"
95 if ! which parted
&>/dev
/null
; then
96 echo "$0: error: install parted"
100 case $2 in swap|boot
) : ;; *) echo "$0: error: bad 2nd arg"; usage
1 ;; esac
102 #### end arg error checking ####
106 [[ $2 == boot
]] || boot
=false
108 op_size
=$1 # operator plus size
109 [[ $op_size != *g
]] || op_size
=$
(( ${op_size%g} / 1024 ))
112 if [[ $op_size == +* ]]; then
113 op_size_rev
=-$size # rev = reverse
121 ##### end command line parsing ########
127 reboot_script_initialized
=false
133 p mkpart primary
"$4" \
134 $
((${ptable[start$part]} $start_op)) $
((${ptable[end$part]} $end_op))
141 e
() { echo "+ $@"; "$@"; }
148 while read devid dev
; do
152 while IFS
=: read id start end psize _
; do
153 [[ $id == [0-9] ]] ||
continue
154 ptable
[start
$id]=start
=${start%%[^0-9]*}
155 ptable
[end
$id]=${end%%[^0-9]*}
156 ptable
[size
$id]=${psize%%[^0-9]*}
157 done < <(parted
-m /dev
/$dev unit MiB print
)
158 parted
/dev
/$dev unit MiB print |
tee /root
/backup_partition_table_
$dev
159 p
() { e parted
-a optimal
-s -- /dev
/$dev unit MiB
"$@"; }
160 e systemctl stop systemd-cryptsetup@crypt_swap_
$dev$swapn
161 sleep 1 # dunno if this is needed,
162 # but systemd likes to do these kind of things in the background.
164 # These partition comments seems a little verbose now, but I bet they
165 # will be helpfull if I read this in more than a week from now.
166 # <> = deleted partition, () = partition
167 p
rm $swapn # ( root )< swap >( boot )
169 root_resize_cmd
="e btrfs fi resize $devid:${op_size_rev}M /"
170 if $grow; then $root_resize_cmd; fi
172 # < root >< swap >( boot )
173 # ( root ) >< swap >( boot )
175 # < root >< swap >( boot )
176 # ( root >< ) swap >( boot )
178 out
=$
(p
rm $rootn 2>&1)
181 pmk
$rootn "" $op_size_rev
184 grep "but we have been unable to inform the kernel" &>/dev
/null
; then
188 if $needs_reboot; then
189 e systemctl mask dev-mapper-crypt_swap_
$dev$swapn.swap
190 e systemctl mask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
191 e
() { echo "$@" >> /root
/finish-resize
; }
192 if ! $reboot_script_initialized; then
193 reboot_script_initialized
=true
194 rm -rf /root
/finish-resize
195 cat >/root
/finish-resize
<<'EOF'
198 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
200 chmod +x
/root
/finish-resize
202 e systemctl unmask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
203 e systemctl unmask dev-mapper-crypt_swap_
$dev$swapn.swap
208 boot_devid
=$
(btrfs
fi show
/boot | \
209 sed -rn "s#^\s*devid\s+(\S+)\s.*$dev[0-9]#\1#p")
212 # shrink boot, move it to a temp file
213 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
215 temp_boot
=/root
/temp_boot_
$dev
216 e
dd bs
=1M
if=/dev
/$dev$bootn of
=$temp_boot \
217 count
=$
((${ptable[size$bootn]} $op_size))
222 # ( root ) >< swap >< boot >
223 # ( root )( >< swap ) >< boot >
224 # ( root )( >< swap )( >< boot )
226 # ( root >< ) swap >< boot >
227 # ( root >< )( swap >< ) boot >
228 # ( root >< )( swap >< )( boot )
230 pmk
$swapn $op_size_rev $op_size_rev "linux-swap"
231 pmk
$bootn $op_size_rev ""
234 e
dd bs
=1M
if=/dev
/$dev$bootn of
=/dev
/$dev$bootn skip
=$size
236 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
238 e
dd bs
=1M
if=$temp_boot of
=/dev
/$dev$bootn
242 # if $grow; then ( root )( >< swap )( boot )
243 # else ( root >< )( swap )( boot )
244 pmk
$swapn $op_size_rev "" "linux-swap"
245 e systemctl start systemd-cryptsetup@crypt_swap_
$dev$swapn
247 done < <(btrfs
fi show
/ | \
248 sed -nr 's#^\s*devid\s*(\S+)\s.*_([^_ ]+)[0-9]\s*$#\1 \2#p')
252 e
rm -rf "/root/temp_boot_*"
253 e
rm -f /root
/finish-resize
256 if $needs_reboot; then
258 echo "$0: Reboot, run /root/finish-resize. It's contents:"
259 cat /root
/finish-resize
261 echo "$0: If you want to resize again later, a reboot is required first."
264 echo "$0: rebooting now"