The following command-line tool automatically creates partitions, is compatible with all Linux distributions, automatically recognizes the system name, and is simple, convenient, and practical.
Note that you must log in as the root user to perform this operation. Regular users must force log out before executing the command.
1. Check if /opt has enough space for the backup? Potential risk: The script's first step will completely package /home into /opt/home.tar.gz. If your /opt directory is actually under the root directory /, and the root directory is almost full, the tar backup will be interrupted due to insufficient disk space. Security recommendation: Before running, execute df -h /opt to ensure that the available space in /opt is greater than the total used space in /home.
2. The user logging in remotely via SSH must not be a user under /home! Potential risk: If you are currently logged in as a regular user (e.g., admin, whose home directory is /home/admin), and then switch to root using su -, when executing the second step fuser -km /home, the system will instantly disconnect your SSH connection, causing the script to terminate directly in the background. Since the old volume has been deleted and the new volume has not been created, the system will crash. Security recommendation: You must modify the SSH configuration to allow the root user to log in remotely, or run the script in the background in a tmux/screen virtual terminal.
3. Potential Risks in File System Type Confirmation: The script hardcodes `mkfs.xfs` and `xfs_growfs`. If your system was installed using the Ext4 file system (common in Debian/Ubuntu, and some older versions of CentOS), executing these commands will result in an error and crash, triggering a rollback. Security Recommendation: Before running the script, be sure to execute `df -T /home` to confirm that the `Type` column displays `xfs`.
Simply enter the numerical size of your home space.
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
`disk_resize.sh 100`
100 sets the home directory space size in GB, which cannot exceed 3/2 of the hard drive size. The remaining space is automatically allocated to the `/` root directory. Very convenient.
To ensure absolute security:
# 1. Create a 20GB secure snapshot (named root_backup) for the current root directory.
The system will instantly rewind time, perfectly restoring all data, partitions, and environment to the state just before you executed the script. No system reinstallation is required! If the script executes successfully and you're sure there are no problems: type the command `lvremove /dev/mapper/almalinux-*_backup` to delete the snapshot; it won't take up any extra space.