ddrescue перезагружает USB-устройство на тайм-аут чтения

У меня поврежден внешний USB жесткий диск. Когда я подключаю устройство к компьютеру, я могу получить доступ к файловой системе примерно за минуту. После этого периода диск продолжает вращаться, но время каждой операции истекает.

Чтобы спасти мои данные, которые я хочу использовать ddrescue но так как устройство перестает работать каждую минуту, это не восстановится, если я не перезагружаю USB-устройство каждый раз, когда происходит тайм-аут чтения, поскольку наиболее вероятной причиной этого является то, что устройство снова зависает. Есть ли способ позволить ddrescue выполнить команду оболочки или около того, когда происходит тайм-аут чтения?

Невозможно подключить внешний жесткий диск через sata, так как внутри нет доступного разъема sata.

3 ответа

Я знаю, что никто не будет читать это, поэтому я не буду вдаваться в подробности. И очень жаль, потому что это единственный метод, который работает.

ПРОБЛЕМА: Попытка спасти множество ценных фотографий с жесткого диска с большим количеством поврежденных секторов. Когда программное обеспечение для чтения сталкивается с неисправным сектором, оно зависает (перестает отвечать на запросы), и единственное, что вы можете сделать, это отключить USB.

Испытанные вещи: (не работает)

Все программы обещают, что они "пропускают плохие сектора без остановки". Ложь.

  • DataRescue DD. Упрощенный и устаревший.
  • EaseUS Восстановление данных. Восстанавливается, пока не найдет плохой сектор.
  • HDD Raw Copy Tool.
  • Расстались с магией. Это так же, как использование простого дистрибутива Linux + ddrescue.
  • Clonezilla. Перепробовал несколько настроек: VM, Live CD; USB и SATA соединения.
  • Опция AOMEI Backupper "Дисковый клон". Ничего не клонирует.
  • Опция WinHex Clone Disk.
  • EaseUS Partition Master.

Кроме того, эти инструменты не позволяют выбрать блок резюме.

Не пробовал: DeepSpar Disk Imager (аппаратное обеспечение, стоит $3000+).

ПОДХОД К РЕШЕНИЮ

ddrescue - это сложная программа, в которой все настраивается. Он работает на Linux и Windows (с Cygwin). Учебник. Я не смог запустить DDRescue-GUI (некоторая ошибка XOpenDisplay), кроме GUI, более простого, чем командная строка.

Вещи пытались с ddrescue. Некоторые люди предложили некоторые обходные пути:

  • Запустите ddrescue в цикле и установите параметры времени ожидания, которые останавливают выполнение.
  • Измените время ожидания жесткого диска ОС для ускорения. / SYS / блок / SDB / устройство / тайм-аут
  • Перезагрузите жесткий диск USB изнутри. /sys/bus/usb/drivers/usb unbind-bind; usb_modeswitch -v 0x.... -p 0x.... --reset-usb. Использование диспетчера устройств Windows такое же.
  • Завершить процесс восстановления (killall, taskkill). Пример скрипта. Не работает, так как процесс не отвечает.

РЕШЕНИЕ

  1. Хост с виртуальной машиной (VirtualBox). Хост запускает сервер, который прослушивает команды присоединения / отсоединения и отправляет их на виртуальную машину.

  2. Гостевая виртуальная машина Windows, которая запускает сценарий менеджера, который управляет рабочим процессом: запуск / остановка ddrescue, отправка команд присоединения / отсоединения на хост и продвижение позиции в файле карты.

Виртуальная машина Linux (Debian) не работала. После отсоединения VirtualBox говорит: "Не удалось подключить USB-устройство к виртуальной машине"

####Script1 server.py runs in host####
import subprocess
from bottle import route, run

exe = "C:/Program Files/Oracle/VirtualBox/VBoxManage.exe"
vm = "Win7"
id = "54a7249b-930a-4d49-a679-9a7b8810adcc"  # VBoxManage list usbhost

def execute(cmd):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
    (output, err) = p.communicate()
    p_status = p.wait()
    res = output.decode("utf-8")
    if "error" in res:
        return "1"
    else:
        return "0"
    return

@route('/attach')
def cmd1():
    res = execute('"' + exe + '" controlvm ' + vm + " usbattach " + id)
    return res

@route('/detach')
def cmd2():
    res = execute('"' + exe + '" controlvm ' + vm + " usbdetach " + id)
    return res

run(host='0.0.0.0', port=80)

,

####Script2 manager.py runs in guest####
import requests 
import subprocess
import time
import re
import os

def get_id(disk):
    p = subprocess.Popen("wmic diskdrive get Index, Model", stdout=subprocess.PIPE, shell=True)
    (output, err) = p.communicate()
    p_status = p.wait()
    res = output.decode("utf-8")
    lines = res.splitlines()
    id = ""
    for line in lines:
        if line.find(disk) > 1:
            id = line[0]
    return id

def check_disk(disk):
    p = subprocess.Popen("wmic diskdrive get Model", stdout=subprocess.PIPE, shell=True)
    (output, err) = p.communicate()
    p_status = p.wait()
    res = output.decode("utf-8")
    if disk in res:
        return 1
    else:
        return 0

def mod_disk(disk, cmd):
    v=1 if cmd=='attach' else 0
    for i in range(3):
        response = requests.get('http://192.168.1.20/'+cmd)
        res = response.content.decode("utf-8")
        if "0" in res:
            while True:
                if(check_disk(disk)==v):
                    break
                time.sleep(1)
                print("[" + disk + " " + cmd + " wait]")
            print("[" + disk + " " + cmd + " ok]")
            break
        time.sleep(3)

def dec2hex(n):
    return "%X" % n

def hex2dec(s):
    return int(s, 16)

def update_mapfile():
    skip = 5000000 #5Mb
    with open(mapfile, 'r') as file:
        data = file.readlines()
    line7 = data[6]
    p = re.compile('^0x(.*?) ')
    hval = p.findall(line7)[0] 
    dval = hex2dec(hval)
    dval2 = dval + skip
    hval2 = dec2hex(dval2)
    line7b = re.sub(hval, hval2, line7)
    data[6] = line7b
    with open(mapfile, 'w') as file:
        file.writelines(data)

############################
disk = "WD 3200AAJ"
mapfile = "E:/mapfile.log"
inpt = "/dev/sdb" if get_id(disk) == "1" else "/dev/sdc"
cmdl = 'c:/cygwin/bin/ddrescue.exe -v -d -n -O ' + inpt + ' E:/image.img E:/mapfile.log'

#Start ddrescue
proc = subprocess.Popen(cmdl, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)
print("Start ddrescue")
time.sleep(60)

while True:
    ft = os.path.getmtime(mapfile)
    n = time.time()
    if n-ft > 60:
        #send sigterm
        p = subprocess.Popen('taskkill /f /fi "imagename eq ddrescue.exe"', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
        (output, err) = p.communicate()
        p_status = p.wait()
        print("send sigterm")
        #detach HDD
        mod_disk(disk, 'detach')
        time.sleep(2)
        print("detach HDD")
        #update modfile
        update_mapfile()
        print("update modfile")
        #attach HDD
        mod_disk(disk, 'attach')
        time.sleep(2)
        print("attach HDD")
        #restart ddrescue
        inpt = "/dev/sdb" if get_id(disk) == "1" else "/dev/sdc"
        cmdl = 'c:/cygwin/bin/ddrescue.exe -v -d -n -O ' + inpt + ' E:/image.img E:/mapfile.log'
        proc = subprocess.Popen(cmdl, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)
        print("restart ddrescue")
    time.sleep(60)

Очевидно, вам нужно будет адаптировать конфигурацию к вашей системе.

Есть ли способ позволить ddrescue выполнить команду оболочки или около того, всякий раз, когда происходит тайм-аут чтения?

Нет, но вы можете использовать это:

-T interval
--timeout=interval
Максимальное время, прошедшее с момента последнего успешного чтения, перед тем как сдаться. По умолчанию до бесконечности. [...]

-X n
--max-read-errors=n
Максимальное количество ошибок чтения, разрешенных до отказа. По умолчанию до бесконечности. Выход со статусом 1 если больше чем n ошибки чтения встречаются [...]

и беги ddrescue в цикле (mapfile является обязательным, так ddrescue возобновляет, а не восстанавливает) вместе с "командой оболочки или около того".

Я думаю, в некоторых обстоятельствах это может помочь:

-O
--reopen-on-error
Закройте infile, а затем снова открывайте его после каждой ошибки чтения, возникшей на этапе копирования. [...]

В противном случае этот вопрос может быть.

Чтобы спасти свои данные, я хочу использовать ddrescue, но поскольку устройство перестает работать каждую минуту.

В общем, единственный способ избежать этого — выключить и включить привод.

Я не уверен, можно ли как-то настроить автоматический запуск с помощью ddrescue, однако HDDSuperClone может.

Хотя эта страница относится к версии Pro, она уже неактуальна, поскольку HDDSuperClone теперь имеет открытый исходный код:

HDDSuperClone Pro теперь также способен напрямую управлять переключаемыми USB-концентраторами серии YEPKIT YKUSH. Это вариант вместо необходимости модифицировать удлинительный кабель USB для использования с обычным реле. Более подробную информацию о платах YEPKIT можно найти по следующей ссылке:

https://www.yepkit.com

Самый простой, вероятно, использование встроенного переключаемого USB-концентратора YKUSH. Итак, настройка оборудования выглядит так:

      host > usb > ykush > usb drive

Другие вопросы по тегам