Created
February 28, 2026 11:53
-
-
Save MrZoidberg/8f11a1ba09403a9f5524eaddb6903c07 to your computer and use it in GitHub Desktop.
Enlarge disk size inside debian/ubuntu VM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| # Simple helper to print info | |
| log() { echo -e "\e[1;34m[INFO]\e[0m $*"; } | |
| warn() { echo -e "\e[1;33m[WARN]\e[0m $*"; } | |
| err() { echo -e "\e[1;31m[ERR]\e[0m $*" >&2; } | |
| if [[ $EUID -ne 0 ]]; then | |
| err "This script must be run as root." | |
| exit 1 | |
| fi | |
| # Check for required tools | |
| for cmd in lsblk findmnt parted growpart; do | |
| if ! command -v "$cmd" &>/dev/null; then | |
| err "Required command '$cmd' not found. Install it and re-run." | |
| if [[ "$cmd" == "growpart" ]]; then | |
| echo " On Ubuntu: apt update && apt install -y cloud-guest-utils" | |
| fi | |
| exit 1 | |
| fi | |
| done | |
| # ---- Detect root mount ---- | |
| root_src=$(findmnt -n -o SOURCE /) | |
| root_fstype=$(findmnt -n -o FSTYPE /) | |
| log "Root filesystem: $root_src (type: $root_fstype)" | |
| is_lvm=false | |
| if [[ "$root_src" == /dev/mapper/* ]]; then | |
| is_lvm=true | |
| fi | |
| # ---- Helper to grow a partition to end of disk ---- | |
| grow_partition() { | |
| local part_dev="$1" | |
| # Underlying disk (e.g. sda for sda3, nvme0n1 for nvme0n1p3) | |
| local disk_name | |
| disk_name=$(lsblk -no PKNAME "$part_dev") | |
| local disk_dev="/dev/${disk_name}" | |
| # Partition name relative to disk (e.g. sda3 -> 3, nvme0n1p3 -> 3) | |
| local part_name | |
| part_name=$(basename "$part_dev") | |
| # Extract numeric partition index (handle sdX#, vdX#, nvmeXnYp#) | |
| local part_num | |
| part_num=$(echo "$part_name" | sed 's/[^0-9]*//g') | |
| if [[ -z "$part_num" ]]; then | |
| err "Could not determine partition number for $part_dev" | |
| exit 1 | |
| fi | |
| log "Disk device: $disk_dev" | |
| log "Partition dev: $part_dev (partition #$part_num)" | |
| log "Growing partition $part_dev to fill $disk_dev using growpart..." | |
| growpart "$disk_dev" "$part_num" | |
| log "Partition growth completed." | |
| } | |
| # ---- Non-LVM root case ---- | |
| resize_plain_root() { | |
| local part_dev="$1" | |
| local fstype="$2" | |
| grow_partition "$part_dev" | |
| case "$fstype" in | |
| ext4|ext3) | |
| log "Resizing ext filesystem on $part_dev with resize2fs..." | |
| resize2fs "$part_dev" | |
| ;; | |
| xfs) | |
| # xfs_growfs works on the mounted filesystem, use the mountpoint | |
| if ! command -v xfs_growfs &>/dev/null; then | |
| err "xfs_growfs not found, install xfsprogs (apt install -y xfsprogs)." | |
| exit 1 | |
| fi | |
| log "Resizing XFS filesystem on / with xfs_growfs..." | |
| xfs_growfs / | |
| ;; | |
| *) | |
| err "Unsupported filesystem type '$fstype' for plain root. Aborting." | |
| exit 1 | |
| ;; | |
| esac | |
| log "Plain root filesystem resize completed." | |
| } | |
| # ---- LVM root case ---- | |
| resize_lvm_root() { | |
| local lv_dev="$1" | |
| # Find the PV backing this LV (assume single PV) | |
| local pv_dev | |
| pv_dev=$(pvs --noheadings -o pv_name "$lv_dev" 2>/dev/null | awk '{$1=$1};1' | head -n1 || true) | |
| if [[ -z "$pv_dev" ]]; then | |
| err "Could not determine PV for LV $lv_dev. Is LVM set up normally?" | |
| exit 1 | |
| fi | |
| log "Detected PV for root LV: $pv_dev" | |
| # Grow the underlying partition | |
| grow_partition "$pv_dev" | |
| # Resize PV to take new space | |
| log "Resizing PV $pv_dev with pvresize..." | |
| pvresize "$pv_dev" | |
| # Extend LV to use all free space, and grow filesystem in-place (-r) | |
| log "Extending LV $lv_dev to use all free space (lvextend -r -l +100%FREE)..." | |
| lvextend -r -l +100%FREE "$lv_dev" | |
| log "LVM root resize completed." | |
| } | |
| # ---- Main logic ---- | |
| if [[ "$is_lvm" == false ]]; then | |
| log "Detected non-LVM root." | |
| if [[ "$root_src" != /dev/* ]]; then | |
| err "Unexpected root source: $root_src (not a /dev device). Aborting." | |
| exit 1 | |
| fi | |
| resize_plain_root "$root_src" "$root_fstype" | |
| else | |
| log "Detected LVM root: $root_src" | |
| if ! command -v pvs &>/dev/null || ! command -v lvextend &>/dev/null; then | |
| err "LVM tools not found. Install lvm2 (apt install -y lvm2) and retry." | |
| exit 1 | |
| fi | |
| resize_lvm_root "$root_src" | |
| fi | |
| log "All done. Current block devices:" | |
| lsblk |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment