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 ]] ||
exec sudo
"$BASH_SOURCE" "$@"
53 Usage: ${0##*/} [OPTIONS] +/-SIZE[g] swap|boot
55 Assuming Ian Kelling's partition scheme, Resize swap or boot, expanding
56 or shrinking the root fs and partition to compensate. If it changes
57 the partition tables incorrectly, the originals are stored in
58 /root/backup_partition_table_<device_names>.
61 -r Reboot now if it's needed.
62 -h|--help Print help and exit.
64 SIZE is MiB, or if g is specified, GiB.
66 If using multiple devices, SIZE is applied to each device, so total change is
69 Note: Uses GNU getopt options parsing style
77 temp
=$
(getopt
-l help rnh
"$@") || usage
1
81 -r) reboot_now
=true
; shift ;;
82 -n) dry_run
=true
; shift ;;
85 *) echo "$0: Internal error!" ; exit 1 ;;
89 #### begin arg error checking ####
91 if [[ $# != 2 ]]; then
92 echo "$0: error: expected 2 arguments"
96 if [[ $1 != [+-][0-9]* ]]; then
97 echo "$0: error: bad 1st arg: $1"
101 if ! which parted
&>/dev
/null
; then
102 echo "$0: error: install parted"
106 case $2 in swap|boot
) : ;; *) echo "$0: error: bad 2nd arg"; usage
1 ;; esac
108 #### end arg error checking ####
112 [[ $2 == boot
]] || boot
=false
114 op_size
=$1 # operator plus size
115 if [[ $op_size == *g
]]; then
119 size
=$
(( ${size} * 1024 ))
125 if [[ $op_size == +* ]]; then
126 op_size_rev
=-$size # rev = reverse
133 ##### end command line parsing ########
139 reboot_script_initialized
=false
141 pmk
() { # partition make
147 # This fails outside a vm, but actually succeeds. also prints this
149 # Error: Partition(s) 2 on /dev/sda have been written, but
150 # we have been unable to inform the kernel of the change, probably
151 # because it/they are in use. As a result, the old partition(s)
152 # will remain in use. You should reboot now before making further
155 p mkpart primary
"$fs_type" \
156 $
((${ptable[start$part]} $start_op)) $
((${ptable[end$part]} $end_op)) ||
:
163 e
() { echo "+ $@"; "$@"; }
170 while read devid dev
; do
171 if [[ $dev != /dev
/mapper
/* ]]; then
172 # older oses, it points to /dev/dm-x
173 dev
=$
(dmsetup info
$dev |
sed -rn 's/^\s*Name:\s*(\S*)/\1/p')
175 dev
=${dev#/dev/mapper/}
177 dev
=${dev#crypt_dev_}
180 dev
=${dev%$BASH_REMATCH}
181 devpath
=/dev
/disk
/by-id
/$dev
185 while IFS
=: read id start end psize _
; do
186 [[ $id == [0-9] ]] ||
continue
187 ptable
[start
$id]=start
=${start%%[^0-9]*}
188 ptable
[end
$id]=${end%%[^0-9]*}
189 ptable
[size
$id]=${psize%%[^0-9]*}
190 done < <(parted
-m $devpath unit MiB print
)
191 parted
$devpath unit MiB print |
tee /root
/backup_partition_table_
$dev
192 p
() { e parted
-a optimal
-s -- $devpath unit MiB
"$@"; }
193 unit
=systemd-cryptsetup@crypt_dev_
$dev-part$swapn
194 # note systemctl show can test if a unit exists.
195 e systemctl stop
$unit ||
[[ $?
== 5 ]] # fail due to not loaded
196 # there is a bug in jessie. this and the .swap unit are
197 # generated from /etc/fstab, and it escapes - to x2d, then doesn't escape it
198 # when looking for the file to use as swap. so, no swap is working on jessie
200 sleep 1 # dunno if this is needed,
201 # but systemd likes to do these kind of things in the background.
203 # These partition comments seems a little verbose now, but I bet they
204 # will be helpfull if I read this in more than a week from now.
205 # <> = deleted partition, () = partition
206 p
rm $swapn # ( root )< swap >( boot )
208 root_resize_cmd
="e btrfs fi resize $devid:${op_size_rev}M /"
209 if $grow; then $root_resize_cmd; fi
211 # < root >< swap >( boot )
212 # ( root ) >< swap >( boot )
214 # < root >< swap >( boot )
215 # ( root >< ) swap >( boot )
217 out
=$
(p
rm $rootn 2>&1)
220 pmk
$rootn "" $op_size_rev
223 grep "but we have been unable to inform the kernel" &>/dev
/null
; then
227 if $needs_reboot; then
228 e systemctl mask dev-mapper-crypt_swap_
$dev$swapn.swap
229 e systemctl mask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
230 e
() { echo "$@" >> /root
/finish-resize
; }
231 if ! $reboot_script_initialized; then
232 reboot_script_initialized
=true
233 rm -rf /root
/finish-resize
234 cat >/root
/finish-resize
<<'EOF'
237 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
239 chmod +x
/root
/finish-resize
241 e systemctl unmask systemd-cryptsetup@crypt_swap_
$dev$swapn.service
242 e systemctl unmask dev-mapper-crypt_swap_
$dev$swapn.swap
247 # non by-id path, to match what btrfs fi show will tell us
248 boot_dev_path
=$
(readlink
-f $devpath-part$bootn)
249 boot_devid
=$
(btrfs
fi show
/boot | \
250 sed -rn "s#^\s*devid\s+(\S+)\s.*$boot_dev_path#\1#p")
253 # shrink boot, move it to a temp file
254 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
256 temp_boot
=/root
/temp_boot_
$dev
257 e
dd bs
=1M
if=$boot_dev_path of
=$temp_boot \
258 count
=$
((${ptable[size$bootn]} $op_size))
263 # ( root ) >< swap >< boot >
264 # ( root )( >< swap ) >< boot >
265 # ( root )( >< swap )( >< boot )
267 # ( root >< ) swap >< boot >
268 # ( root >< )( swap >< ) boot >
269 # ( root >< )( swap >< )( boot )
271 pmk
$swapn $op_size_rev $op_size_rev "linux-swap"
272 pmk
$bootn $op_size_rev ""
275 e
dd bs
=1M
if=$boot_dev_path of
=$boot_dev_path skip
=$size
277 e btrfs
fi resize
$boot_devid:${op_size}M
/boot
279 e
dd bs
=1M
if=$temp_boot of
=$boot_dev_path
283 # if $grow; then ( root )( >< swap )( boot )
284 # else ( root >< )( swap )( boot )
285 pmk
$swapn $op_size_rev "" "linux-swap"
286 e systemctl start systemd-cryptsetup@crypt_swap_
$dev$swapn
288 done < <(btrfs
fi show
/ |
sed -nr 's#^\s*devid\s*(\S+).* path (.*)$#\1 \2#p')
292 e
rm -rf "/root/temp_boot_*"
293 e
rm -f /root
/finish-resize
296 if $needs_reboot; then
298 echo "$0: Reboot, run /root/finish-resize. It's contents:"
299 cat /root
/finish-resize
301 echo "$0: If you want to resize again later, a reboot is required first."
304 echo "$0: rebooting now"