Первая версия GNU ddrescue была выпущена 19 лет назад 12 августа 2004г. Но не спешите проматывать статью. Это не очередной пересказ мануала или описание алгоритма работы, коих полно в сети. Сегодня я расскажу о ней кое что новенькое.
О чем же я собрался рассказать, потерпите, все узнаете. Для начала обозначим проблему. Далее по тексту может показаться что повествование будет уклоняться в сторону, но постарайтесь сфокусироваться на сути проблемы.
Проблема и решения
Энтузиастам она известна. Во многих случаях электронные мозги подопытного жесткого диска перестают отвечать на ATA команды по интерфейсу. В этот момент драйвер шлет ему soft и hard reset'ы, но часто и это не помогает.
И тогда пора дергать рубильник, то есть отключать и затем снова подключать ему питание. Для автоматизации процесса приспосабливают реле. Кто через LPT, кто через Raspberry PI а кто USB реле промышленного изготовления.
Не нашел пруфов, но профессиональные DR решения ACELab PC-3000 и DeepSpar Disk Imager тоже должны уметь это. Необходимость в Power-off and power-on cycle и у них иногда возникает. Возможно кто нибудь из причастных уточнит в комментариях.
Критика таких кустарных методов со стороны DR специалистов
Попытаюсь хоть как то охладить причастные места специалистов и возможно даже восстановить их душевное спокойствие. Я тоже считаю такие методы обращения с жесткими дисками дичайшим варварством. Это сродни нажатию пользователем кнопки Reset на корпусе системного блока при зависании ОС. Меня, знающего какие процессы происходят внутри ОС x86 это также сильно коробит. Но внутренности устройства собственных ОС самих жестких дисков (да там у них внутри свои полноценные ОС) покрыты мраком и не доступны большинству интересующихся около компьютерными темами. Возможно поэтому люди к ним так безжалостны.
Отступление по поводу кнопки Reset
Да в компьютерных корпусах эти кнопки до сих пор есть, даже не верится.
Вот современный ноутбук с зависшей Windows 10 так просто не перезагрузишь.
Часто эта ОС зависает так что показывает только черный экран. А по матрице ноутбука и не всегда видно что горит подсветка, и ноутбук на самом деле включен.
Горят только индикаторы включения и зарядки на корпусе. При нажатии на кнопку включения он будет уходить в спящий режим, и снова просыпаться зависшим, пока его не отключат от БП.
А уже полежав без дела какие то часы и высадив в 0% аккумулятор, будучи принесенным в сервис, включится и загрузится там как ни в чем не бывало.
Если кустарное восстановление происходит не с SSD, а с жесткого диска со всеми его движущимися головками и блинами - вытащить данные потом в нормальной DR лаборатории может стать в несколько раз дороже, чем до экспериментов. А может стоить не только денег, но и вообще невозможности что либо вытащить. Поэтому хорошо если экспериментатор понимает свою меру ответственности. И экспериментирует со своими личными дисками, а не с клиентскими. Но об этом к сожалению можно только мечтать. Да здесь должна быть шутка про люди делятся на...
Linux, Windows и неисправные SSD
Я призываю к объективности. Мои выводы основаны на личном практическом опыте в сервисе. Речь о десятках неисправных SSD. Постараюсь объяснить с примерами в чем тут загвоздка. Холивары это не практично!
Не редко SSD как SATA так и NVMe выходят из строя. В о всех случаях из моей практики на SSD была установлена Windows. Это не плюс или минус, просто отсутствие статистики по Linux. В случае неисправности SSD - Windows либо не загружается (висит на лого или заходит в UEFI Setup), либо глючит, зависает, не может установить обновления или корректно завершить работу.
На самом же деле электронные мозги неисправных SSD ведут себя немного по разному. По симптомам можно классифицировать так. Разделить на две основные группы. И каждую из них на подгруппы.
К первой группе относим те случаи когда без ошибок проходит чтение по всем без исключения секторам. А вот если что то попробовать записать возможны варианты:
А. Полный игнор диском любых операций записи, при этом без каких либо ошибок.
Б. Ошибки при записи. Но продолжает быть доступен на чтение.
В. При любой попытке записи - диск с интерфейса пропадает.
Ко второй группе относим случаи когда SSD выдает ошибки уже при чтении. И тут тоже бывают под-варианты:
Г. Ошибки при чтении, но после их обработки диск остается доступен.
Д. При попытке чтения сбойного сектора - перестает читать что либо вообще.
По моему опыту нормально скопировать данные с неисправного SSD при подключении к другому ПК с Windows можно только в некоторых случаях из подгрупп А и Б. Когда диск работает стабильно - то есть не зависает и не пропадает из системы. Это если повезет.
Здесь и далее я имею в виду обычное подключение к интерфейсу SATA / NVMe / USB и работу с драйверами от Microsoft из состава ОС. Без специализированных прокладок между ОС и диском, роль коих могут играть DR программно-аппаратные комплексы.
В основном же такие неисправные диски при подключении к Windows ведут себя странно. В большинстве случаев это выглядит как виден в проводнике, но проводник висит. Или определяется и тут же пропадает.
Linux дает возможность исследовать поведение SSD, и попытаться, а в случае если у диска проблемы только с записью - то гарантированно вытащить данные.
Далее в статье речь пойдет о решении которое я создал для облегчения работы со случаями из подгруппы Д. А именно о автоматизации процесса копирования без необходимости аппаратных примочек для Power-off and power-on cycle.
Отступление по поводу производственных утилит MPTool от производителей контроллеров для OEM производителей SSD
Производственные утилиты MPTool (под Windows) и сами прошивки регулярно утекают из подвалов поднебесной в большой интернет.
Но программный ремонт это не про спасение данных. Это восстановление нормальной работоспособности накопителя с полным и безвозвратным уничтожением данных.
Известная возможность ядра Linux
В Linux есть возможность отключать и подключать на горячую SATA (и даже IDE) устройства, дергая вызовы через /sys
интерфейс. Об этом есть статья на хабре от 2010г, но приведу здесь нужные команды.
Отключение диска sudo echo 1 > /sys/block/sdX/device/delete
Где X
это буква алфавита
Подключение диска sudo echo '0 0 0' > /sys/class/scsi_host/hostN/scan
Где N
это цифра
Отступление про IDE (он же PATA, а не то что могли подумать при виде вроде бы примелькавшейся аббревиатуры)
Еще в 2010г использовал на Soc-775 дешевых платах с ICH7. Одна была от Asus другая от Gigabyte. И там и там никакого Hot Plug не было.
Linux можно было подключить и отключить SATA и IDE диски даже если они не были воткнуты в порты изначально при включении компа. Любые IDE диски из тех что прошли через сервис также корректно определялось как и SATA.
Но на одной из двух плат если включить без IDE диска изначально. То порядок этих самых scsi_host/hostN
менялся, их становилось меньше. Хост который отвечал за два диска на IDE контроллере становился недоступен. Но если включать с IDE диском - то его можно было затем остановить, отключить, и подключить другой!
И проблема стабильности имен SATA / USB устройств
Почему речь о SATA и только о нем, а написано SCSI? Это не очевидно, но в Linux все устройства и SATA и USB подключается через подсистему SCSI. Точнее последовательность такая в случае SATA: libata > sg > sd
. Пояснительную бригаду только не просите присылать. На самом деле все логично.
За реализацию SATA и PATA отвечает
libata
sg
это SCSI Generic слой абстракции через который и запихнуты все SATA и USB устройства в подсистему SCSIsd
- SCSI Device это собственно сама реализация подсистемы SCSI. И через этот по сути верхний уровень абстракции нам видны все SATA и USB устройства. Вот почему мы видим в списке устройств эти непонятные/dev/sda, /dev/sdb
- имена всех устройств начинаются на/dev/sd
Буквы sda sdb sdc
меняются в зависимости от порядка инициализации SATA дисков в системе. И все USB воткнутые диски, и флешки появляются среди них же.
А уж при работе с неисправными нестабильно работающими SSD, которые могут сами по себе отключаться - буква диска может меняться вроде бы непредсказуемо.
Способ адресации SATA устройств по номеру порта
В процессе копания в /sys/class
я обратил внимание на /sys/class/ata_port/ataN
где N
начинается с 1 и соответствует количеству SATA портов на плате.
Все эти /sys/class
и /sys/block
нагромождение вложенных симллинков на директории которые друг на друга ссылаются.
Как получить /sys/class/scsi_host/hostN/scan
из /sys/class/ata_port/ataN
я нашел довольно быстро. Здесь каждому ataN
соответствует только один hostN
/sys/class/ata_port/ata3/device/host2/scsi_host/host2/scan
Но как распутать клубок ссылок ? Запустить readlink
с ключом -f
readlink -f /sys/class/ata_port/ata"$N"/device/host?/scsi_host/host?/
Нужный нам номер SATA порта подставляем в $N
а номера хостов просто заменяем на ?
/sys/block/sdX/device/delete
тоже обнаружился!
/sys/class/ata_port/ata3/device/host2/target2:0:0/2:0:0:0/delete
Здесь придется добавить много ?
readlink -f /sys/class/ata_port/ata"$N"/device/host?/target?:?:?/?:?:?:?/
С получением /dev/sdX
тоже оказалось просто.
readlink -f /dev/disk/by-path/pci-*-ata-"$N"
Все готово. Скрипт написан. Представляю вашему вниманию.
ddrescue-loop v0.1.1
ddrescue-loop v0.1.1
#!/bin/sh
#ddrescue-loop script writen by gumanzoy <gumanzoy@gmail.com>
# Compatible only with Linux, not with other *nix!
# Depends on udev /dev and sysfs /sys kernel interfaces
# Requires SATA AHCI compatible motherboard
# For all Intel and modern AMD platforms (AM4 and newer), check the UEFI Setup
# SATA settings to ensure Port Hot Plug is enabled
# [RU] forum thread. Обсуждение
# https://forum.ixbt.com/topic.cgi?id=11:47589-31
# /* This program is free software. It comes without any warranty, to
# * the extent permitted by applicable law. You can redistribute it
# * and/or modify it under the terms of the Do What The Fuck You Want
# * To Public License, Version 2, as published by Sam Hocevar. See
# * http://www.wtfpl.net/ for more details. */
VERSION=0.1.1
showhelp () {
echo "ddrescue-loop v""$VERSION"" перезапускает процесс ddrescue в случае его завершения"
echo "Внимание следует соблюдать очередность аргументов"
echo "Указывать ключи в произвольном порядке нельзя!"
echo "Числовые значения аргументов обязательно через пробел"
echo -n "\n"
echo "# Остановить/запустить диск на SATA порту:"
echo "-ata <n> -stop"" ""остановить диск на SATA порту <n>"
echo "-ata <n> -scan"" ""сканировать SATA порт <n>"
echo -n "\n"
echo "# Запустить восстановление:"
echo "ddrescue-loop -ata <n> [-loop <n>] [-wait <n>] [-act <n>] outfile mapfile [ddrescue options]"
echo -n "\n"
echo "# Укажите номер SATA порта к которому подключен диск источник:"
echo -n "-ata <n>"" ""Номер SATA порта <n> цифра (смотрите вывод dmesg)"
echo -n "\n"" ""#: "; ls /sys/class/ata_port
echo -n "\n"
echo "# Функция циклической остановки/перезапуска диска на SATA порту:"
echo "-loop <n>"" ""<n> предельное число попыток"
echo -n "\n"
echo "# Таймер ожидания остановки/перезапуска диска:"
echo "-wait <n>"" ""Время в секундах <n> [10]"
echo -n "\n"
echo "# Переопределить таймаут ожидания исполнения ATA команд:"
echo "-act <n>"" ""Время в секундах <n> [30]"
echo -n "\n"
echo "# Основные:"
echo "outfile"" ""Устройство приемник данных / файл образа"
echo "mapfile"" ""ddrescue map/log файл (обязательно)"
echo -n "\n"
echo "# В конце после mapfile можно указать опции запуска ddrescue через пробел"
echo "# Поддержка зависит от версии. Полный список опций в мануале. Важные:"
echo "-P [<lines>]"" ""Предпросмотр данных [число строк] по умолчанию 3"
echo "-b 4096"" ""Размер сектора (физического блока) [default 512]"
echo "-O"" #Рекомендую! ""После каждой ошибки заново открывать файл устройства"
echo "-J"" #Опционален ""При ошибке перечитать последний не сбойный сектор"
echo "-r <n> #ИЛИ -r -1"" ""<n> число повторных проходов до перехода к trim"
echo "-m <domain.mapfile>"" ""Ограничить область чтения доменом <file> ddru_ntfsbitmap"
}
get_ata_host () {
until SCSIHOST=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/scsi_host/host?/` \
&& test -d "$SCSIHOST"; do sleep 1; done
}
get_ata_target () {
until SYSFSTGT=`readlink -f /sys/class/ata_port/ata"$1"/device/host?/target?:?:?/?:?:?:?/` \
&& test -d "$SYSFSTGT"; do sleep 1; done
}
get_ata_dev () {
until INDEV=`readlink -f /dev/disk/by-path/pci-*-ata-"$1"` \
&& test -b "$INDEV"; do sleep 1; done
}
if [ "$1" = "-h" -o "$1" = "--help" ]; then showhelp
exit; fi
if [ "`whoami`" != "root" ]; then
echo Exit. This script should be run as root !
exit 1; fi
if [ -n "$1" ] && [ "$1" = "-ata" ]; then
if [ -n "$2" ] && test -d /sys/class/ata_port/ata"$2"; then
SATAP="$2"; get_ata_host "$SATAP"; shift; shift
else echo -n "Please enter correct port number: "; ls /sys/class/ata_port; exit 1; fi
fi
if [ -n "$1" ] && [ "$1" = "-loop" ]; then
if [ -n "$2" ] && [ "$2" -gt 0 ]; then
DDLOOP="$2"; shift; shift; fi
else DDLOOP=0
fi
if [ -n "$1" ] && [ "$1" = "-wait" ]; then
if [ -n "$2" ] && [ "$2" -gt 0 ]; then
LOOPWAIT="$2"; shift; shift; fi
else LOOPWAIT=10
fi
if [ -n "$1" ] && [ "$1" = "-act" ]; then
if [ -n "$2" ] && [ "$2" -gt 0 ]; then
ATACMDT="$2"; shift; shift; fi
fi
if [ -n "$1" ] && [ "$1" = "-stop" ] && [ -n "$SATAP" ]; then
get_ata_target "$SATAP"
while test -f "$SYSFSTGT"/delete; do echo 1 > "$SYSFSTGT"/delete; sleep 1; done
exit; fi
if [ -n "$1" ] && [ "$1" = "-scan" ] && [ -n "$SATAP" ]; then
echo '0 0 0' > "$SCSIHOST"/scan; exit; fi
if [ -z "$SATAP" ]; then showhelp
exit; fi
OUTFILE="$1"; shift
MAPFILE="$1"; shift
DDOPTS="$@"
DONE=X
LOOPCOUNT=0
until [ "$DONE" = 0 ]; do
get_ata_target "$SATAP"; get_ata_dev "$SATAP"
if [ -n "$ATACMDT" ]; then echo "$ATACMDT" > "$SYSFSTGT"/timeout
fi
echo ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" "$DDOPTS"
ddrescue "-fd" "$INDEV" "$OUTFILE" "$MAPFILE" $DDOPTS
DONE="$?"
if [ "$DONE" != 0 ] && [ "$DDLOOP" -gt 0 ]; then
sleep "$LOOPWAIT"
while test -d "$SYSFSTGT"; do echo 1 > "$SYSFSTGT"/delete
sleep "$LOOPWAIT"; done
sleep "$LOOPWAIT" && echo '0 0 0' > "$SCSIHOST"/scan
DDLOOP=$(($DDLOOP-1))
LOOPCOUNT=$(($LOOPCOUNT+1))
echo "\n\033[1mDDLOOP" "#""$LOOPCOUNT"
tput sgr0
date
echo -n "\n"
else DONE=0
fi
done
Исправление v0.1.1 что изменилось
Один участок кода. Убрано ограничение 30 для параметра -act
Старый вариант:
if [ -n "$1" ] && [ "$1" = "-act" ]; then
if [ -n "$2" ] && [ "$2" -gt 0 -a "$2" -lt 30 ]; then
ATACMDT="$2"; shift; shift; fi
fi
Исправленный:
if [ -n "$1" ] && [ "$1" = "-act" ]; then
if [ -n "$2" ] && [ "$2" -gt 0 ]; then
ATACMDT="$2"; shift; shift; fi
fi
Теперь можно задавать таймаут больше чем установлен по умолчанию в ядре Linux. Оказалось что это позволяет ядру дожидаться ответа диска вместо оправок команды ataN: hard resetting link
![This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2 This program is free software. It comes without any warranty, to the extent permitted by applicable law. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2](https://habrastorage.org/getpro/habr/upload_files/31b/20d/602/31b20d602980df104a0c3bf01dbe38fe.png)
Системные требования
Скрипт будет работать только в Linux так как использует интерфейсы ядра
udev /dev
иsysfs /sys
Для работы с SSD вообще желательно плату с поддержкой AHCI
На платформах Intel начиная с Soc-1156 и на AMD AM4/AM5 нужно включать Hot Plug в UEFI BIOS Setup для каждого порта отдельно.
На более старых AMD, но у которых в чипсете поддержка AHCI есть - сразу должно работать ничего специально включать не надо.
На Intel Soc-775 после ICH7 не уверен, но можете пробовать. На ICH7 и более старых ничего хорошего не выйдет - там нет поддержки AHCI.
Как этим пользоваться
Неисправный SSD нужно подключать уже после загрузки системы. Ни в коем случае не сразу при включении!
ddrescue-loop -ata N -stop
Остановить диск на SATA порту N
ddrescue-loop -ata N -scan
Cканировать SATA порт N
Номер соответствует порту на мат.плате, но нумерация всегда начинается с 1, а не с 0 как на платах Gigabyte например. Если не уверены то смотрите выхлоп dmesg
Насколько можно быть уверенным в этих номерах ?
Возможно порядок может меняться при перезагрузке системы. Особенно на платах с несколькими контроллерами.
Но между перезагрузками системы эти номера стабильны. Твердо и четко!
ddrescue-loop -ata N [-loop N] [-wait N] [-act N] outfile mapfile [ddrescue options]
Так как я не слишком искушен в sh скриптинге, и вообще не программист - с разбором параметров особо не мудрствовал. Поэтому есть некоторые важные ограничения!
Следует соблюдать очередность аргументов. Указывать ключи в произвольном порядке нельзя!
Числовые значения аргументов обязательно через пробел.
А как же автоматизация. Ради чего все затевалось
Функция циклической остановки/перезапуска диска на SATA порту:-loop N
Предельное число попыток N
целое число. Указывать обязательно.
Таймер ожидания остановки/перезапуска диска:-wait N
Время в секундах. 10 по умолчанию.
Ограничения применимости автоматизации к жестким дискам!
Сразу скажу что не для жестких дисков это. А для SATA SSD и только для них!
То есть исправные жесткие диски таким методом останавливаются/запускаются без проблем.
Но вот многие неисправные в зависшем состоянии не остановятся после команды стоп пока питание не выдернуть.
Переопределить таймаут ожидания исполнения ATA команд:-act N
Время в секундах. 30 по умолчанию в Linux.
В конце после mapfile
можно указать опции запуска ddrescue. Их обрабатывает уже сама ddrescue, можно указывать все как обычно.
В качестве outfile
я обычно указываю образ, смонтированный в /dev/loopN
Напрямую на другое устройство не пишу. Но можно и просто файл образа указывать.
В общем все как обычно с ddrescue
Вместо заключения
Возможно сегодня еще есть люди которые скептически относятся к open source решениям. Но оглянитесь вокруг и сравните как было 15 лет назад и как сейчас. Я считаю что чем в большее количество сфер проникнут решения на базе открытого кода - тем лучше для всех. Да для всех без исключения. Надеюсь что хоть в этом направлении наш мир движется правильно.
Говоря о сфере DR и самих аппаратно-программных составляющих накопителей с открытостью пока все печально. А ведь при большей открытости со стороны производителей можно было бы добиться лучшей надежности хранения данных.
Сторонникам проприетарности посоветую вспомнить историю с выводом на рынок SMR моделей жестких дисков. Кому от такого подхода лучше стало, уж точно не пользователям.
Благодарю за внимание! И удачных экспериментов!