The remaining disk space will automatically be allocated to:
/
Script Workflow
The complete workflow:
1. Check system environment
ā
2. Detect LVM configuration
ā
3. Backup /home data
ā
4. Unmount /home
ā
5. Remove old /home volume
ā
6. Extend root volume
ā
7. Create new /home volume
ā
8. Format XFS filesystem
ā
9. Restore user data
ā
10. Restore permissions
ā
11. Complete
Complete Script
The following script contains:
Environment validation
LVM automatic detection
Disk safety checks
Backup mechanism
Error handling
Rollback protection
Data restoration
Permission recovery
cat << 'EOF' > /root/disk_resize.sh
#!/bin/bash
# Ensure the script triggers the error trap immediately on failure to prevent partial crashes
trap 'on_error' ERR
on_error() {
echo -e "\nā WARNING: Exception triggered during script execution! Initiating rollback mechanism..."
# If the home volume is missing, try to restore the original state
if ! lvs | grep -q "home"; then
echo "Attempting to recreate default home volume to safeguard the boot system..."
lvcreate -L ${CURRENT_HOME_SIZE_G}G -n home $VG_NAME || true
mkfs.xfs -f /dev/mapper/${VG_NAME}-home || true
mount /dev/mapper/${VG_NAME}-home || true
fi
echo "ā ļø Emergency rollback complete. System cleared from deadlock risk. Please check errors above, DO NOT reboot!"
exit 1
}
# ==================== [Strict Numeric Parameter Validation] ====================
if [ -z "$1" ]; then
echo "ā ERROR: Missing target size parameter!"
echo "š” Usage: $0 [integer_only]"
echo " Example: $0 97"
exit 1
fi
INPUT_SIZE="$1"
if [[ ! "$INPUT_SIZE" =~ ^[0-9]+$ ]]; then
echo "ā FORBIDDEN: For production safety, unit suffixes (such as G, GB, M, K) are strictly prohibited!"
echo "š” Correct approach: Enter numbers only. For 97GB, type: $0 97"
exit 1
fi
NUMERIC_SIZE=$INPUT_SIZE
TARGET_SIZE="${NUMERIC_SIZE}G"
if [ "$NUMERIC_SIZE" -le 5 ]; then
echo "ā SAFETY BLOCK: The new size for /home must be [greater than 5GB]!"
exit 1
fi
echo "=== [Verification] Comprehensive environment, disk boundaries, and inode risks check ==="
if [ "$EUID" -ne 0 ]; then
echo "ā ERROR: Do not use sudo or a standard user to run this script! Please log in directly as root."
exit 1
fi
if pwd | grep -q "^/home"; then
echo "ā ERROR: Your current working directory is inside /home! Please switch out by running 'cd /root'."
exit 1
fi
VG_NAME=$(lvs --noheadings -o vg_name /dev/mapper/*-home | head -n1 | tr -d ' ')
if [ -z "$VG_NAME" ]; then
echo "ā ERROR: Failed to automatically detect the Volume Group (VG) name!"
exit 1
fi
export VG_NAME
HOME_LV_PATH="/dev/mapper/${VG_NAME}-home"
ROOT_LV_PATH="/dev/mapper/${VG_NAME}-root"
VG_TOTAL_SIZE_G=$(vgs --noheadings -o vg_size --units g $VG_NAME | head -n1 | grep -o -E '[0-9]+' | head -n1)
MAX_ALLOWED_SIZE=$(( (VG_TOTAL_SIZE_G * 2) / 3 ))
if [ "$NUMERIC_SIZE" -ge "$MAX_ALLOWED_SIZE" ]; then
echo "ā LIMIT EXCEEDED: The requested ${NUMERIC_SIZE}GB reaches or exceeds the maximum safety cap of ${MAX_ALLOWED_SIZE}GB (2/3 of total space)!"
exit 1
fi
CURRENT_HOME_SIZE_G=$(df -G /home | awk 'NR==2 {print $2}' | grep -o -E '[0-9]+' || df -h /home | awk 'NR==2 {print $2}' | grep -o -E '[0-9]+' | head -n1)
export CURRENT_HOME_SIZE_G
if [ -n "$CURRENT_HOME_SIZE_G" ]; then
if [ "$NUMERIC_SIZE" -ge "$CURRENT_HOME_SIZE_G" ]; then
echo "ā SAFETY CIRCUIT: The new size must be [smaller] than the current total size (${CURRENT_HOME_SIZE_G}GB)!"
exit 1
fi
fi
USED_HOME_SIZE_G=$(df -G /home | awk 'NR==2 {print $3}' || df -h /home | awk 'NR==2 {print $3}' | grep -o -E '[0-9]+' | head -n1)
if [ -n "$USED_HOME_SIZE_G" ]; then
if [ "$NUMERIC_SIZE" -le "$USED_HOME_SIZE_G" ]; then
echo "ā SAFETY BLOCK: The input value must be [greater] than the currently used space: ${USED_HOME_SIZE_G}GB!"
exit 1
fi
fi
CURRENT_INODES_USED=$(df -i /home | awk 'NR==2 {print $3}')
ESTIMATED_NEW_INODES=$(( NUMERIC_SIZE * 200000 ))
if [ "$CURRENT_INODES_USED" -gt "$ESTIMATED_NEW_INODES" ]; then
echo "ā INODE EXHAUSTION WARNING: Too many small files detected. Insufficient space will trigger an inode crash!"
exit 1
fi
USER_NAME=$(ls /home/ | head -n1 | tr -d ' ')
if [ "$USER_NAME" = "lost+found" ] || [ -z "$USER_NAME" ]; then USER_NAME=""; fi
echo "=== [1/5] Starting system data backup ==="
df -hT
tar -zcvf /opt/home.tar.gz -C /home .
echo "ā Data successfully backed up to /opt/home.tar.gz"
echo "--------------------------------------------------------"
echo "ā ļø ā ļø ā ļø [CRITICAL WARNING: PROCEEDING TO PHYSICAL DISK ALTERATION] ā ļø ā ļø ā ļø"
echo " All environment metrics passed verification. Backup completed."
echo " Press [Enter] to execute disk resizing. If you are unsure, press [Ctrl + C] to exit safely!"
echo "--------------------------------------------------------"
read -r -p "Confirm and proceed? [Enter]"
echo "=== [2/5] Force unmounting volume ==="
fuser -km /home || true
umount /home
echo "=== [3/5] Removing old volume and fully extending root directory ==="
lvremove -f $HOME_LV_PATH
lvextend -l +100%FREE $ROOT_LV_PATH
xfs_growfs /
echo "=== [4/5] Recreating custom-sized [ ${TARGET_SIZE} ] home volume ==="
lvcreate -L $TARGET_SIZE -n home $VG_NAME
mkfs.xfs -f $HOME_LV_PATH
mount $HOME_LV_PATH
echo "=== [5/5] Restoring user data and permissions ==="
tar -zxvf /opt/home.tar.gz -C /home/
if [ -n "$USER_NAME" ]; then chown -R ${USER_NAME}:${USER_NAME} /home/${USER_NAME}/; fi
# Clear error trap context upon successful execution
trap - ERR
echo "=== š Congratulations, all automated actions completed successfully! System is secure! ==="
df -h
EOF
chmod +x /root/disk_resize.sh
Example
Resize `/home` to 100GB:
/root/disk_resize.sh 100
The script will:
Backup existing `/home`
Release old `/home` space
Expand `/`
Create a new `/home`
Restore all files
Additional Protection: LVM Snapshot Backup
For important production systems, creating an LVM snapshot before modification is strongly recommended.