lvm 扩容脚本
一、需求
1、对已经分区好的/backup进行卸载,把空间扩容到/healsci
2、对新磁盘sdb这种,加入逻辑卷,扩容空间到/healsci
3、可进行功能选择,要做哪一种扩容
二、代码
#!/bin/bash
# set -e
# Get partition mount paths and volume group name
get_mount_points() {
BACKUP_MOUNT_POINT=$(df --output=target | grep /backup)
HEALSCI_MOUNT_POINT=$(df --output=target | grep /healsci)
if [ -z "$HEALSCI_MOUNT_POINT" ]; then
echo "/healsci partition is not mounted correctly, please check the system status."
exit 1
fi
VG_NAME=$(lvdisplay | grep 'VG Name' | head -n 1 | awk '{print $3}')
BACKUP_LV_PATH=$(lvdisplay | grep 'LV Path' | grep "$VG_NAME/backup" | awk '{print $3}')
HEALSCI_LV_PATH=$(lvdisplay | grep 'LV Path' | grep "$VG_NAME/healsci" | awk '{print $3}')
echo '-------------------------------'
echo "VG Name: $VG_NAME"
echo "Backup LV Path: $BACKUP_LV_PATH"
echo "Healsci LV Path: $HEALSCI_LV_PATH"
echo -e '----------------------------\n'
}
# Function 1: Expand /backup to /healsci
expand_backup() {
# Check if rsync is installed
if ! command -v rsync &> /dev/null; then
echo "rsync is not installed, please install it before running this script."
exit 1
fi
if [ -z "$BACKUP_MOUNT_POINT" ]; then
echo "/backup partition is not mounted, please check the system status."
exit 1
fi
# Get space before expansion in bytes
BEFORE_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs)
# Synchronize data
rsync -avh --progress /backup/ "$HEALSCI_MOUNT_POINT/backup/"
# Unmount /backup partition
umount /backup || {
echo "/backup is in use and cannot be unmounted."
lsof +D /backup
exit 1
}
echo "Successfully unmounted /backup"
# Remove the logical volume
lvremove -f "$BACKUP_LV_PATH"
# Extend the healsci volume group
lvextend -l +100%FREE "$HEALSCI_LV_PATH"
# Extend the filesystem
FS_TYPE=$(df -T "$HEALSCI_LV_PATH" | awk 'NR==2 {print $2}')
if [ "$FS_TYPE" == "ext4" ]; then
resize2fs "$HEALSCI_LV_PATH"
elif [ "$FS_TYPE" == "xfs" ]; then
xfs_growfs "$HEALSCI_LV_PATH"
else
echo "Unsupported filesystem type: $FS_TYPE"
exit 1
fi
# Get space after expansion in bytes
AFTER_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs)
# Calculate expanded space in bytes
EXPANDED_SPACE=$(($AFTER_SPACE - $BEFORE_SPACE))
# Display results in human-readable format
echo "Space before expansion: $(numfmt --to=iec $BEFORE_SPACE)"
echo "Space after expansion: $(numfmt --to=iec $AFTER_SPACE)"
echo "Expanded by: $(numfmt --to=iec $EXPANDED_SPACE)"
# Update /etc/fstab
sed -i '/\/backup/d' /etc/fstab
# Create a symbolic link
rm -rf /backup
ln -s /healsci/backup /backup
echo "Function 1 completed: /backup has been successfully expanded to /healsci!"
}
# Function 2: Add a new disk to LVM
add_new_disks() {
while true; do
# List all unformatted disks
UNFORMATTED_DISKS=$(lsblk -dn -o NAME,TYPE | while read -r disk type; do
if [ "$type" = "disk" ] && [ "$disk" != "sr0" ]; then
if [ -z "$(lsblk -no FSTYPE "/dev/$disk")" ]; then
echo "$disk"
fi
fi
done)
if [ -z "$UNFORMATTED_DISKS" ]; then
echo "No unformatted disks available for use."
exit 1
fi
echo "Available disks:"
for disk in $UNFORMATTED_DISKS; do
echo "$disk"
done
read -p "Please select the disk to add to LVM (e.g., sdb or sdb,sdc): " SELECTED_DISKS
# Convert comma or space separated input to space-separated array
SELECTED_DISKS=$(echo "$SELECTED_DISKS" | tr ', ' ' ')
SELECTED_DISK_ARRAY=($SELECTED_DISKS)
# Check if each selected disk is valid
valid=true
for SELECTED_DISK in "${SELECTED_DISK_ARRAY[@]}"; do
SELECTED_DISK=$(echo "$SELECTED_DISK" | xargs)
# Check if the disk is in the unformatted disk list
if ! echo "$UNFORMATTED_DISKS" | grep -qw "$SELECTED_DISK"; then
echo "The selected disk $SELECTED_DISK is not in the unformatted disk list, please re-enter."
valid=false
break
fi
done
if ! $valid; then
continue
fi
# Get space before expansion in bytes
BEFORE_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs)
# Process all valid disks
for SELECTED_DISK in "${SELECTED_DISK_ARRAY[@]}"; do
echo "Adding disk /dev/$SELECTED_DISK to LVM"
pvcreate "/dev/$SELECTED_DISK"
vgextend "$VG_NAME" "/dev/$SELECTED_DISK"
# Confirm the logical volume exists
if ! lvdisplay "$HEALSCI_LV_PATH" &>/dev/null; then
echo "Logical volume does not exist, please check the settings."
exit 1
fi
lvextend -l +100%FREE "$HEALSCI_LV_PATH"
# Extend the filesystem
FS_TYPE=$(df -T "$HEALSCI_LV_PATH" | awk 'NR==2 {print $2}')
if [ "$FS_TYPE" == "ext4" ]; then
resize2fs "$HEALSCI_LV_PATH" || { echo "Failed to extend the filesystem"; exit 1; }
elif [ "$FS_TYPE" == "xfs" ]; then
xfs_growfs "$HEALSCI_LV_PATH" || { echo "Failed to extend the filesystem"; exit 1; }
else
echo "Unsupported filesystem type: $FS_TYPE"
exit 1
fi
# Get space after expansion in bytes
AFTER_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs)
# Calculate expanded space in bytes
EXPANDED_SPACE=$(($AFTER_SPACE - $BEFORE_SPACE))
# Display results in human-readable format
echo "Space before expansion: $(numfmt --to=iec $BEFORE_SPACE)"
echo "Space after expansion: $(numfmt --to=iec $AFTER_SPACE)"
echo "Expanded by: $(numfmt --to=iec $EXPANDED_SPACE)"
echo "Disk /dev/$SELECTED_DISK has been successfully added to LVM!"
done
echo "Function 2 completed: Selected disks have been successfully added to LVM!"
break
done
}
# Main Program
get_mount_points
echo "Please select a number to perform the corresponding function:"
echo "1) Expand /backup to /healsci"
echo "2) Add new disks to LVM"
echo "3) Execute all the above functions"
echo
read -p "Please enter your choice [1/2/3]: " CHOICE
case $CHOICE in
1)
expand_backup
;;
2)
add_new_disks
;;
3)
expand_backup
add_new_disks
;;
*)
echo "Invalid option, please enter 1, 2, or 3."
exit 1
;;
esac
echo "All operations completed!"
三、重点逻辑
1、未格式化分区磁盘的判断
UNFORMATTED_DISKS=$(lsblk -dn -o NAME,TYPE | while read -r disk type; do
if [ "$type" = "disk" ] && [ "$disk" != "sr0" ]; then
if [ -z "$(lsblk -no FSTYPE "/dev/$disk")" ]; then
echo "$disk"
fi
fi
done)
拆解与解释
**UNFORMATTED_DISKS=$(...)**:
这是一个命令替换的结构,将命令的输出结果存储在变量 UNFORMATTED_DISKS 中。
**lsblk -dn -o NAME,TYPE**:
lsblk 是一个列出磁盘和块设备的命令
-d 选项表示只显示磁盘,不显示分区
-n 选项表示不打印标题行
-o NAME,TYPE 选项指定输出显示列,具体是设备名称 (NAME) 和设备类型 (TYPE)
输出类似于
sda disk sdb disk sr0 rom
**| while read -r disk type; do ... done**:
管道符 (|) 将 lsblk 的输出传递给 while 循环。循环会逐行读取上面的输出,将每行的设备名称赋值给变量 disk,将设备类型赋值给变量 type。
**if [ "$type" = "disk" ] && [ "$disk" != "sr0" ]; then**:
该条件判断当前读取的设备类型是否为 "disk",并且设备名称不是 "sr0"(通常是光驱设备)。
如果条件满足,代码块会执行下面的内容。
**if [ -z "$(lsblk -no FSTYPE "/dev/$disk")" ]; then**:
lsblk -no FSTYPE "/dev/$disk" 命令用于检查当前设备的文件系统类型 (FSTYPE)。
-n 选项表示不输出标题。
-o FSTYPE 指定只输出文件系统类型。
-z 检查命令的输出是否为空;即,无文件系统格式则返回 true。
如果该设备没有文件系统,代码块会执行下面的内容。
**echo "$disk"**:
如果前面的条件(设备是磁盘且没有文件系统)满足,则输出该设备名称 ($disk)。
2、扩容空间的计算
BEFORE_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs) AFTER_SPACE=$(df --output=size -B1 "$HEALSCI_MOUNT_POINT" | tail -n 1 | xargs) EXPANDED_SPACE=$(($AFTER_SPACE - $BEFORE_SPACE)) echo "Space before expansion: $(numfmt --to=iec $BEFORE_SPACE)" echo "Space after expansion: $(numfmt --to=iec $AFTER_SPACE)" echo "Expanded by: $(numfmt --to=iec $EXPANDED_SPACE)"
补充
2.1 numfmt 是一个命令行工具,用于在不同的数字格式之间进行转换。它在处理数值的表示和转换时非常有用,尤其是在需要人类可读的格式与用于计算的纯数字格式之间进行转换时。
--to=iec 选项是 numfmt 的一个参数,用于将数字转换为人类可读的格式,并使用 IEC(International Electrotechnical Commission)单位前缀。这种格式主要用于表示数据存储的尺寸和处理速度等,单位包括:
KiB(kibibyte)= 1024 字节MiB(mebibyte)= 1024 KibibytesGiB(gibibyte)= 1024 MebibytesTiB(tebibyte)= 1024 Gibibytes
# numfmt --to=iec 4852936458240 4.5T
2.2 df --output=size -B1
在 df 命令中,--output=size 和 -B1 选项结合使用,用于指定输出格式和块大小:
-
--output=size: 这个选项指定要输出的列为“size”,即文件系统的总大小。这是df的自定义输出功能之一,允许用户选择只显示某些感兴趣的数据列。 -
-B1: 这个选项将块大小设置为字节,df默认显示的单位是以 1K(kilobyte)为计量单位
df --output --help FIELD_LIST is a comma-separated list of columns to be included. Valid field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent', 'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page).
3、打印文件系统的类型
df -T /healsci | awk 'NR==2 {print $2}'
-T 参数输出文件系统类型
NR是行,NF是列
NR==2 {print $2} 打印第二行第二列

浙公网安备 33010602011771号