Знакът на КАГАМИ КАГАМИ
kagami.bg/academy · lesson · machine-readable viewVERIFIED 2026-10-01 · UPDATED 2026-10-01
IDENTITY
module
KW I12 · Rescuing data from an old NAS over the network
series
KAGAMI Way · Track I — Infrastructure
level
Intermediate
duration
~15 min
trust_label
VERIFIED 2026-10-01 (commands and options checked against current man pages and kernel sources) · UPDATED 2026-10-01 · not re-run for this edition, so no TESTED label
language
human view: bg · english edition: /en/academy/moduli/KW_I12_Data_Rescue.html
next
KW_I21_Model_Sync.html · Syncing and copying models between nodes
PURPOSE

Recover data from old single-disk md "linear" ext4 volumes of a Zyxel NSA325 onto a revived NSA325 over the network. Covers: reading a volume the running kernel cannot assemble via a read-only loop device at the partition offset; a CIFS-safe rsync flag set; four field traps; the security cost of SMBv1 and when it is acceptable; a resumable systemd oneshot service.

KEY CONCEPTS
COMMANDS / PATHS (placeholders, no secrets)
CHECKLIST
NEXT MODULE

KW_I21_Model_Sync.html · Syncing and copying models between nodes · offer: Quick experiment (kagami.bg/stalbata/)

SOURCES
TAGS
data-rescueloop-mountrsynccifssmbv1ext4ddrescuesystemdnas
ПРОВЕРЕНО · 01.10.2026 ОБНОВЕНО · 01.10.2026

Спасяване на данни от стар NAS през мрежата

Реален случай: данни от стари дискове на Zyxel NSA325 (ext4 върху md „linear“ том) се връщат върху съживен NSA325 с 4 TB диск, по мрежата. Ще видиш как се чете том, който ядрото не сглобява, как се копира през CIFS без да се удариш в капаните — и какво реално рискуваш с SMBv1.

⏱ ~15 мин Средно Инфраструктура rsync · CIFS · loop-mount
losetup / mount🔒 локално rsync🔒 локално ddrescue🔒 локално systemd🔒 локално
🔄
Обновено 01.10.2026 — какво
Добавени са „Преди да започнеш“, предупреждение за сигурността на SMBv1 и ddrescue за повредени дискове. Офсетът, опциите на losetup, mount и rsync и поддръжката на SMBv1 в ядрото са сверени с документацията. Поправено е, че --inplace вече включва --partial; уточнено е, че ядра 6.8–6.13 нямат linear, а 6.14 и по-нови го имат отново. Адресите, имената на хостове, споделяния и потребители и вътрешните пътища са заменени с плейсхолдъри. Командите не са пускани наново за това издание, затова няма етикет „ТЕСТВАНО“.

01Какво ще научиш

02Преди да започнеш

03Стъпки

  1. Правило номер едно: източникът е само за четене

    Старите томове са single-disk md „linear“ томове с ext4 от Zyxel NSA325; целта е съживен NSA325 с 4 TB диск. Копираме по мрежата (CIFS/SMB). Не рискуваме единственото копие — затова четем само за четене на всеки слой: loop устройство и монтиране.

    ЕтапОписание
    Стар NSA325 дискlinear ext4 том · само за четене · никога не се пише в него
    loop-mount + rsyncЧетем тома през loop устройство, копираме с CIFS-безопасни флагове
    Съживен NSA3254 TB цел, достъпна по мрежата (CIFS/SMB)
    💾
    Диск, който се чупи — първо образ
    Ако дискът дава грешки при четене, rsync върху него може да го довърши. ddrescue не записва нули на мястото на лошите сектори и води mapfile, така че можеш да го прекъснеш и да продължиш. Пример от ръководството му (за дял):
    ddrescue -f -n /dev/sdX2 /път/образ.img /път/mapfile и после ddrescue -d -f -r3 /dev/sdX2 /път/образ.img /път/mapfile. Работиш върху образа, не върху диска. Ръководството казва да ползваш mapfile, освен ако не знаеш какво правиш.
  2. Loop-mount трикът

    Първо провери дали изобщо ти трябва. Опцията MD_LINEAR липсва в изходния код на ядрата 6.8 до 6.13 (проверено в техните drivers/md/Kconfig; в 6.7 още я има) и е отново там в 6.14, 6.17 и текущия master. Дистрибуционните ядра могат да се различават — виж своето: modinfo linear или grep MD_LINEAR /boot/config-$(uname -r). В нашия случай ядрото беше 6.8 и не можеше да сглоби стария том като md, затова го заобиколихме: монтираме дяла през loop устройство с офсет, само за четене.

    bash · намери офсета и монтирай
    # Офсет = начален сектор на дяла × размер на сектора (виж "Start" и "Sector size")
    fdisk -l /dev/sdX
    # При нас дялът почваше от сектор 2048: 2048 × 512 = 1 MiB
    losetup --find --show --read-only --offset $((2048*512)) /dev/sdX2
    # --show печата името на устройството, напр. /dev/loop0; noload пропуска ext4 журнала
    mount -o ro,noload /dev/loop0 /mnt/old
    # проверка
    ls -la /mnt/old
    ✅
    Защо тези опции
    Според losetup(8) --read-only прави устройството само за четене, а --offset премества началото на данните с толкова байта. Според ext4(5) noload не зарежда журнала.
    ⚠️
    Два капана тук
    1. Ако файловата система не е била размонтирана чисто, noload води до несъгласувани данни — ext4 документацията го казва изрично. Затова при съмнение работи върху образ (стъпка 1) и пусни e2fsck върху него. 2. Офсетът 2048 е за нашия диск. Ако md метаданните стоят в началото на члена, данните може да почват по-късно (виж „Data Offset“ в mdadm --examine); това не е проверено от нас ⚠️ — не копирай офсета сляпо.
  3. rsync през CIFS — безопасни флагове

    CIFS целта отхвърля част от операциите, които rsync прави по подразбиране: временен файл + преименуване, смяна на собственик и права. Затова ползваме флагове, които пишат директно и не пипат атрибути, които NAS-ът отказва.

    ФлагЗащо
    --inplaceПише директно във файла вместо да създава ново копие и да го премества. Подразбира и --partial (прекъснат файл не се трие). Цената: файлът е в несъгласувано състояние, докато се копира, и остава такъв при прекъсване.
    --no-perms --no-owner --no-groupИзключва права и собственик, които -a иначе включва
    --omit-dir-timesНе пипа времената на директориите
    -rt --modify-window=2Рекурсия и запазване на времената; два времена се смятат за равни, ако се разминават най-много с 2 секунди. Ръководството посочва 1 за файлови системи с 2-секундна точност (FAT); 2 е стойността, с която минахме при нас
    --info=progress2Общ прогрес на целия пренос (rsync от 3.1.0)
    bash · копиране, което може да се пуска отново
    # Повторно пускане сравнява размер и време и прескача вече копираното
    rsync -rt --modify-window=2 --inplace --no-perms --no-owner --no-group --omit-dir-times --info=progress2 /mnt/old/ /mnt/target/dest/
    ⛔
    Не добавяй -a сляпо
    -a е съкращение за -rlptgoD — влече права, собственик и групи, които CIFS целта отхвърля. Обратното също важи: без -l символните връзки не се копират. Ако в данните има такива, ще ги пропуснеш мълчаливо — прегледай изхода или ги обработи отделно.
    bash · проверка преди да обявиш успех
    # Само сравнява (-n), по контролни суми (-c) — бавно, но надеждно; списъкът показва какво се различава
    rsync -rtnc --itemize-changes /mnt/old/ /mnt/target/dest/

    Опциите в тази проверка са потвърдени в rsync(1), но самата комбинация не е пускана в нашия случай.

  4. Четирите капана от случая

    Това са наблюдения от реалното спасяване върху NSA325. Документацията не ги потвърждава изрично ⚠️ — приеми ги като полеви опит, не като закон.

    ⚠️
    Капан 1 — „close failed: Permission denied (13)“
    На CIFS целта rsync се провали при преименуването на временния файл. Лекува се с --inplace — пише директно, без преименуване.
    ⚠️
    Капан 2 — mkdir дава „Permission denied“ заради квота
    На том с квота (имаше aquota.user файл, макар томът да е почти празен) създаването на папка се отхвърляше с общо „Permission denied“. Пренасочихме към том, който приема запис. Реалната корекция на квотата е през уеб интерфейса на NAS-а. Преди да търсиш грешка в правата, потърси такъв файл.
    ⚠️
    Капан 3 — df показва фалшив размер
    През SMBv1 NSA325 върна df с размер, който не отговаряше на диска (3.6T). Не го ползвай като измерител на прогреса.
    ⚠️
    Капан 4 — du забива под натоварване
    du през CIFS се заби, докато rsync работеше. Чети прогреса от самия rsync (--info=progress2) в журнала, като превърнеш връщането на каретката в нов ред:
    bash · прогрес — не df, не du
    journalctl -u rescue.service -o cat | tr '\r' '\n' | grep %
  5. Монтиране на SMBv1 споделяне — и цената му

    ⛔
    SMBv1 е слаба защита — ползвай го само временно и изолирано
    SMBv1 е най-старият диалект на протокола. Документацията на ядрото обяснява, че SMB 2.1 и по-новите имат допълнителна защита — срещу „човек по средата“ и по-силни хешове — и затова старите диалекти се препоръчват да не се ползват. Ръководството на mount.cifs казва, че SMB1 вече не се иска по подразбиране при монтиране и има „много по-слаба сигурност“. Samba по подразбиране има минимален протокол SMB2_02, а Microsoft отдавна призовава „Stop using SMB1“.

    Затова: само в изолирана мрежа (директен кабел или отделен суич, без интернет и чужди устройства); само докато трае спасяването; с данни за вход, които не ползваш никъде другаде; размонтирай и изключи услугата след края. Най-добре: ако можеш, извади диска и го чети директно със стъпка 2, вместо да вдигаш SMBv1.

    Старият NSA325 в нашия случай работеше само по SMBv1: със vers=2.0/2.1 монтирането завършваше с „Host is down“. Ако виждаш това, подозирай версията. Дали по-нов фърмуер на NSA325 говори SMB2 — не сме проверявали ⚠️.

    ℹ️
    Поддръжка в ядрото днес
    В Linux master опцията CIFS_ALLOW_INSECURE_LEGACY е включена по подразбиране; ако е изключена, vers=1.0 и vers=2.0 не се приемат. Модулът има и параметър disable_legacy_dialects=y, който изключва SMB1. Дистрибуционните ядра не сме проверявали ⚠️ — ако vers=1.0 се отхвърля, това може да е причината. В прегледаните източници не е обявено премахване на SMB1, но не разчитай, че ще е там завинаги.
    bash · монтирай с vers=1.0
    # Файл с данни за вход, четим само от root; формат по mount.cifs(8): редове username= и password=
    touch /root/.nas-credentials && chmod 600 /root/.nas-credentials
    mount -t cifs //<nas-host>/<share> /mnt/target -o credentials=/root/.nas-credentials,vers=1.0
    # „Host is down“? Почти сигурно е версията — върни се на vers=1.0

    Данните за вход са във файл, не в командния ред — така не се виждат в списъка с процеси и в историята на обвивката.

  6. Трайна услуга — оцелява спиране на тока

    systemd услуга от тип oneshot се счита за пуснала, когато главният ѝ процес приключи — подходящо за еднократна задача. Нашата при всяко стартиране пресъздава loop устройството, монтира NAS-а и възобновява rsync (прескача вече копираното). След рестарт просто продължава. Изключи услугата, когато приключиш.

    systemd · пример (илюстрация, не е пускан тук)
    [Unit]
    Description=Data rescue (resumable copy)
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/sbin/rescue.sh
    
    [Install]
    WantedBy=multi-user.target
    sh · rescue.sh — идемпотентно (илюстрация)
    #!/bin/sh
    set -eu
    # Име по by-id, не /dev/sdX — след рестарт буквите на дисковете могат да се сменят
    SRC=/dev/disk/by-id/<disk-id>-part2
    mountpoint -q /mnt/old || {
      LOOP=$(losetup --find --show --read-only --offset $((2048*512)) "$SRC")
      mount -o ro,noload "$LOOP" /mnt/old
    }
    mountpoint -q /mnt/target || mount -t cifs //<nas-host>/<share> /mnt/target -o credentials=/root/.nas-credentials,vers=1.0
    rsync -rt --modify-window=2 --inplace --no-perms --no-owner --no-group --omit-dir-times --info=progress2 /mnt/old/ /mnt/target/dest/
    ℹ️
    Защо е безопасно да се пуска многократно
    Логиката е идемпотентна: ако нещо вече е монтирано, скриптът го пропуска; rsync продължава оттам, докъдето е стигнал. Прекъснатият с --inplace файл е в несъгласувано състояние, но следващото пускане го презаписва, защото размерът и времето му не съвпадат. При съмнение, след края пусни проверката от стъпка 3.

04Проверка

1. Ядрото няма linear модул. Как четеш стария том?

2. rsync дава „close failed: Permission denied (13)“ на CIFS целта. Кой флаг помага?

3. df показва фалшив размер, а du се заби. Как следиш прогреса?

4. Защо услугата oneshot оцелява спиране на тока?

5. Защо SMBv1 (vers=1.0) се ползва само временно и в изолирана мрежа?

05Какво следва

06Източници

  1. losetup(8) — --read-only, --offset, --find --show.
  2. ext4(5) — noload/norecovery и предупреждението за несъгласуваност.
  3. rsync(1) — --inplace (подразбира --partial), -a = -rlptgoD, --omit-dir-times, --modify-window, --info=progress2.
  4. mount.cifs(8) — vers=, формат на файла credentials=, раздел „Security“, disable_legacy_dialects.
  5. Linux: fs/smb/client/Kconfig — CIFS_ALLOW_INSECURE_LEGACY и защо старите диалекти се избягват.
  6. Linux 6.8: drivers/md/Kconfig (без MD_LINEAR) и master (с него).
  7. GNU ddrescue — ръководство — mapfile и примерите за дял.
  8. smb.conf(5) — client min protocol и server min protocol, по подразбиране SMB2_02.
  9. Microsoft: Stop using SMB1.
  10. systemd.service(5) — Type=oneshot.
  11. Полеви опит на КАГАМИ: спасяване на данни от стари дискове на NSA325 върху съживен NSA325 (капаните в стъпка 4 са от него).