← شروع آموزش

WIUNIX ACADEMY

افزایش ظرفیت LV و فایل‌سیستم XFS یا ext4 بدون unmount

صفحهٔ 2 از 3؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.

آموزش متناسب با محیط تو

کجا اجرا می‌کنی؟

سیستم‌عامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راه‌حل‌های همون محیط رو ببینی.

Arch Linux rollingبررسی‌شده با مستندات رسمی ·

آموزش متناسب با مقادیر تو

تنظیمات این آموزش

مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه می‌مونن و به سرور یا لینک اشتراک‌گذاری فرستاده نمی‌شن. قبل از اجرا، DNS، گواهی‌ها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.

اگر آی‌پی، دامنه یا پورت‌های نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.

تنظیم مقادیر برای محیط من3 مقدار قابل‌تغییر
05

قدم بعدی

تطبیق مسیر رو دوباره بسنجیم و هدف extent رو حساب کنیم

این نشست Bash رو برای پنل‌های بعدی نگه دار. تابع پایین فقط هویت و ظرفیت رو می‌خونه. اگر mount و LV یکی نباشن، فقط زیرشاخه‌ای از فایل‌سیستم mount شده باشه، دستگاه چند بار mount شده باشه، mount فقط‌خواندنی باشه، نوع LV یا فایل‌سیستم مناسب نباشه یا VG قفل اشتراکی داشته باشه، ادامه رو رد می‌کنه. این کنترل دامنه، سلامت سخت‌افزار رو ثابت نمی‌کنه و جلوی مدیر دیگری رو هم قفل نمی‌کنه.

اندازهٔ نهایی GiB رو به تعداد کامل extent تبدیل می‌کنیم؛ اختلافش با تعداد فعلی می‌گه چه مقدار باید اضافه بشه. اگر LV از قبل به همان هدف رسیده باشه، افزایش لازم صفره. با مسئول ذخیره‌ساز هماهنگ کن تا در این فاصله mount یا چیدمان دستگاه‌ها عوض نشه. اگر شل تازه‌ای باز کردی، این تابع رو دوباره وارد کن؛ فراخوانی‌های بعدی مقدارهای فعلی فرم رو صریح بهش می‌دن.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

export LC_ALL=C
set -o pipefail
plan_growth() {
    mount=$1
    lv=$2
    target_gib=$3
    test -d "$mount" && test -b "$lv" || return 1
    source=$(findmnt -rn --mountpoint "$mount" -o SOURCE) || return 1
    test "$(readlink -f -- "$source")" = "$(readlink -f -- "$lv")" || return 1
    test "$(findmnt -rn --mountpoint "$mount" -o FSROOT)" = / || return 1
    fs=$(findmnt -rn --mountpoint "$mount" -o FSTYPE) || return 1
    case "$fs" in xfs|ext4) ;; *) return 1 ;; esac
    options=$(findmnt -rn --mountpoint "$mount" -o OPTIONS) || return 1
    case ",$options," in *,rw,*) ;; *) return 1 ;; esac
    devno=$(findmnt -rn --mountpoint "$mount" -o MAJ:MIN) || return 1
    mount_count=$(findmnt -rn -o MAJ:MIN | awk -v d="$devno" '$1==d {n++} END {print n+0}') || return 1
    test "$mount_count" -eq 1 || return 1
    attr=$(sudo lvs --noheadings -o lv_attr "$lv" | tr -d '[:space:]') || return 1
    case "$attr" in -w??a*) ;; *) return 1 ;; esac
    types=$(sudo lvs --segments --noheadings -o segtype "$lv" | awk 'NF {print $1}' | sort -u) || return 1
    test "$types" = linear || return 1
    vg=$(sudo lvs --noheadings -o vg_name "$lv" | tr -d '[:space:]') || return 1
    test -n "$vg" || return 1
    locktype=$(sudo vgs --noheadings -o vg_locktype "$vg" | tr -d '[:space:]') || return 1
    case "$locktype" in ''|none) ;; *) return 1 ;; esac
    vgattr=$(sudo vgs --noheadings -o vg_attr "$vg" | tr -d '[:space:]') || return 1
    case "$vgattr" in ??x*|???p*|?????[cs]*) return 1 ;; esac
    current_b=$(sudo lvs --noheadings --units b --nosuffix -o lv_size "$lv" | awk 'NF {printf "%.0f\n",$1}') || return 1
    extent_b=$(sudo vgs --noheadings --units b --nosuffix -o vg_extent_size "$vg" | awk 'NF {printf "%.0f\n",$1}') || return 1
    free_extents=$(sudo vgs --noheadings -o vg_free_count "$vg" | tr -d '[:space:]') || return 1
    case "$current_b:$extent_b:$free_extents:$target_gib" in *[!0-9:]*|:*|*::*) return 1 ;; esac
    test "$extent_b" -gt 0 && test "$target_gib" -ge 1 && test "$target_gib" -le 1024 || return 1
    test $((current_b % extent_b)) -eq 0 || return 1
    target_gib=$((10#$target_gib))
    requested_b=$((target_gib * 1024 * 1024 * 1024))
    target_extents=$(((requested_b + extent_b - 1) / extent_b))
    current_extents=$((current_b / extent_b))
    test "$target_extents" -ge "$current_extents" || return 1
    needed_extents=$((target_extents - current_extents))
    test "$free_extents" -ge "$needed_extents" || return 1
    printf 'mount=%s LV=%s filesystem=%s VG=%s\n' "$mount" "$lv" "$fs" "$vg"
    printf 'current_bytes=%s extent_bytes=%s target_extents=%s additional_extents=%s free_extents=%s\n' "$current_b" "$extent_b" "$target_extents" "$needed_extents" "$free_extents"
}
plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || {
    printf '%s\n' 'STOP: mapping, supported layout, target size or free extents did not pass.'
    exit 1
}
از کجا بفهمم درست انجام شده؟

mount، دستگاه، نوع فایل‌سیستم، VG و محاسبهٔ extent با تغییر مصوب یکی هستن؛ ردشدن کنترل یعنی علت رو بررسی کن، نه اینکه کنترل رو برداری.

06

قدم بعدی

وضعیت قبل و فرادادهٔ همان VG رو نگه داریم

بعد از تأیید بکاپ جداگانهٔ داده، فرادادهٔ VG و چند گزارش کوچک رو در یک پوشهٔ خصوصی تازه با مالکیت root نگه می‌داریم. نام VG از همان LV انتخاب‌شده پیدا شده؛ قرار نیست همهٔ گروه‌ها رو صادر کنیم. مسیر چاپ‌شده رو در سابقهٔ تغییر نگه دار و مدارک لازم رو با روش فعلی تیم به محل محافظت‌شده منتقل کن.

پوشهٔ این مدارک هم به فضای آزاد نیاز داره. اگر روی فایل‌سیستم درگیر ساخته شده، برای بازیابی بعد از خرابی روی اون حساب نکن. موفق‌شدن vgcfgbackup کافی نیست: این فایل نقشهٔ LVها رو ثبت می‌کنه و دادهٔ برنامه یا فایل‌سیستم بزرگ‌شده رو به حالت قبلی برنمی‌گردونه.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || exit 1
record=$(sudo mktemp -d /var/tmp/academy-lvm-growth.XXXXXXXX) || exit 1
sudo vgcfgbackup --file "$record/vg-before.conf" "$vg" || exit 1
sudo lvs --segments -o lv_path,lv_uuid,lv_attr,segtype,lv_size,vg_name,devices "$lv" | sudo tee "$record/lvs-before.txt" >/dev/null || exit 1
findmnt --mountpoint "$mount" -o TARGET,SOURCE,FSTYPE,FSROOT,OPTIONS | sudo tee "$record/mount-before.txt" >/dev/null || exit 1
df -B1 -- "$mount" | sudo tee "$record/df-before.txt" >/dev/null || exit 1
printf 'Private change record: %s\n' "$record"
از کجا بفهمم درست انجام شده؟

وضعیت قبل در یک پوشهٔ خصوصی ثبت شده و راه بازیابی دادهٔ برنامه جدا تأیید شده؛ خطا، کار رو قبل از تغییر ظرفیت متوقف می‌کنه.

07

قدم بعدی

طرح افزایش رو بدون اشتباه‌گرفتن با اجرا بررسی کنیم

هویت و فضای آزاد رو دوباره می‌خونیم و از LVM می‌خواهیم همان هدف نهایی رو در حالت test بررسی کنه. این حالت نوشتن فراداده رو غیرفعال می‌کنه؛ موفقیتش به معنی موفقیت قطعی تخصیص واقعی یا رشد فایل‌سیستم نیست. ممکنه کار دیگری بعد از این بررسی extent آزاد رو مصرف کنه.

کل خروجی رو بخون. اگر LV همین حالا به هدف رسیده، افزایش دیگری بهش اضافه نکن و سراغ مقایسهٔ فایل‌سیستم برو. اگر اندازهٔ فعلی از هدف فرم بزرگ‌تره، طرح رو با مسئولش تطبیق بده؛ کم‌کردن حجم راه حل‌کردن این اختلاف نیست.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || exit 1
if test "$needed_extents" -eq 0; then
    printf '%s\n' 'LV already has the reviewed target size; inspect the filesystem layer next.'
else
    sudo lvextend --test --extents "$target_extents" "$lv" || exit 1
fi
از کجا بفهمم درست انجام شده؟

طرح هدف درست LV و extent رو نشون می‌ده یا اعلام می‌کنه LV از قبل به همان اندازه رسیده و افزایش لازم نیست؛ فایل‌سیستم هنوز جدا باید بررسی بشه.

08

قدم بعدی

فقط لایهٔ LV رو بزرگ کنیم

این اولین پنل تغییر ظرفیت است. درست قبل از درخواست تعداد نهایی extent، هویت و فضای آزاد دوباره کنترل می‌شن. عمداً رشد فایل‌سیستم رو با این کار ترکیب نکردیم تا اگر فقط یک لایه جلو رفت، محل توقف روشن باشه. قفل تخصیص رو خود LVM مدیریت می‌کنه؛ بررسی قبلی ما فضا رو رزرو نکرده.

ترمینال و خطای اصلی رو نگه دار. بعد از برگشت موفق، اندازهٔ بایتی LVM رو با اندازهٔ block device در device-mapper مقایسه کن. ممکنه فایل‌سیستم هنوز همان اندازهٔ قبلی باشه؛ یعنی کار لایهٔ دوم باقی مونده، نه اینکه باید دوباره LV رو بزرگ کنی.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || exit 1
if test "$needed_extents" -eq 0; then
    printf '%s\n' 'LV already has the reviewed target size; no repeated extension.'
else
    sudo lvextend --extents "$target_extents" "$lv" || exit 1
fi
sudo lvs --units b --nosuffix -o lv_path,lv_size,vg_name "$lv"
sudo blockdev --getsize64 "$lv"
از کجا بفهمم درست انجام شده؟

LV و دستگاه زیر آن، هدف گرد‌شدهٔ مصوب رو نشون می‌دن؛ کار روی فایل‌سیستم هنوز باید انجام بشه.

09

قدم بعدی

فقط برای XFS؛ از مسیر mount رشد بدیم

این شاخه رو فقط وقتی اجرا کن که بررسی مسیر، نوع xfs رو نشون داده. کنترل‌ها اول می‌سنجن LV به هدف رسیده، بعد xfs_growfs بخش داده رو از طریق mountpoint موجود بزرگ می‌کنه. فایل‌سیستم باید mount بمونه؛ داشتن مسیر LV جای پیداکردن mount واقعی رو نمی‌گیره.

بعد از کار، مشخصات هندسی و ظرفیت فایل‌سیستم رو بخون. چیدمان با log یا realtime device جدا در دامنه نیست. اگر نوع فایل‌سیستم ext4 است، از کل این شاخه رد شو و پنل بعدی رو انجام بده.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || exit 1
test "$needed_extents" -eq 0 && test "$fs" = xfs || exit 1
sudo xfs_growfs -d "$mount" || exit 1
sudo xfs_info "$mount"
df -B1 -- "$mount"
از کجا بفهمم درست انجام شده؟

بخش دادهٔ XFS mountشده از ظرفیت تازهٔ LV استفاده می‌کنه یا علت مشخصِ تمام‌نشدن رشد گزارش می‌شه.

10

قدم بعدی

فقط برای ext4؛ تا اندازهٔ LV موجود رشد بدیم

این شاخه فقط برای خروجی ext4 است. وقتی به resize2fs اندازه نمی‌دیم، فایل‌سیستم رو تا اندازهٔ دستگاه زیرش بزرگ می‌کنه. کنترل‌ها می‌سنجن دستگاه همان LV مصوبه و قبلاً به هدف رسیده. رشد online به کرنل و قابلیت‌های فایل‌سیستم نصب‌شده وابسته است؛ ردشدن ابزار یعنی علت رو بررسی کن، نه اینکه گزینهٔ force اضافه کنی.

اگر ابزار بررسی آفلاین خواست یا گفت قابلیت رشد پشتیبانی نمی‌شه، توقف کن و نگهداری آفلاین مصوب توزیع رو با مسئول برنامه هماهنگ کن. روی این فایل‌سیستم mountشده ابزار check یا repair اجرا نکن و برنامهٔ فعال رو هم بی‌برنامه unmount نکن. برای XFS از این شاخه رد شو.

bash

همان نشست Bash روی میزبان ذخیره‌ساز مصوب

plan_growth '/srv/data' '/dev/vg_data/lv_data' '20' || exit 1
test "$needed_extents" -eq 0 && test "$fs" = ext4 || exit 1
sudo resize2fs "$lv" || exit 1
df -B1 -- "$mount"
از کجا بفهمم درست انجام شده؟

رشد ext4 کامل می‌شه و فایل‌سیستم mountشده ظرفیت تازه رو نشان می‌ده، یا حالت خطا/پشتیبانی‌نشدن مشخص برای پیگیری باقی می‌مونه.

همهٔ آموزش‌های آکادمی ↗