Cómo recuperar ficheros de discos defectuosos bajo Linux

En un artículo anterior describía unos procedimientos para comprobar la salud de los discos duros de un sistema Linux. El objetivo de dicho artículo era descubrir si los discos presentaban algún tipo de problema físico, recomendando su sustitución lo antes posible. Sin embargo, ¿qué hacemos si queremos recuperar ficheros que tienen partes de los mismos residiendo en sectores defectuosos? Veámoslo, teniendo en cuenta que la información que se encuentre en dichos sectores tiene una alta probabilidad de ser irrecuperable. En este caso, al menos podemos intentar recuperar el contenido accesible, que podemos editar a posteriori.

El método consiste en realizar una copia del fichero con tolerancia a fallos, de forma que cuando se produzca un error de lectura el procedimiento siga adelante y recupere al final la información que sí ha podido leer sin problemas. Para ello contamos con una herramienta clásica de UNIX, el comando dd, tan útil como peligroso si no lo utilizamos bien.

En el caso que nos ocupa, tendremos que indicarle a dd el fichero a recuperar, el destino en el que guardaremos el contenido recuperado y que debe realizar la copia con tolerancia a errores de lectura. El comando completo, que hay que ejecutar como root, sería el siguiente:
# dd if=/home/usuario/fichero of=/media/usbdrive/fichero_limpio conv=noerror,sync

Como se puede ver, la salida se realiza en un dispositivo diferente al disco defectuoso (por ejemplo, un pendrive) para evitar males mayores.

Una vez terminada la copia, sólo resta desechar el disco y sustituirlo por otro en buenas condiciones. POr cierto, debido a los errores de lectura, la copia con dd puede tardar bastante tiempo en llevarse a cabo, sobre todo dependiendo del tamaño del fichero original y de la cantidad de sectores defectuosos por los que hay que pasar. En definitiva, que hay que armarse de paciencia.

Si no queremos deshacernos del disco problemático (por ejemplo, forma parte de un RAID, no tenemos recambio a mano o simplemente lo queremos reutilizar), existe una opción que hay que utilizar como último recurso, ya que se trata de un procedimiento que elimina la información del sector y que tiene un alto grado de riesgo destructivo para todo el sistema de ficheros. Se trata de forzar la relocalización dinámica de sectores defectuosos, algo que los discos suelen llevar a cabo de forma automática por su cuenta pero que en esta ocasión vamos a obligarle a hacer.

Para ello contamos con la herramienta hdparm, la cual ya mencionamos en el artículo anterior. Pero antes de comenzar con la relocalización, comprobaremos si el disco ya ha reasignado sectores en el pasado. Hay que tener en cuenta que cada disco duro ofrece un número máximo de sectores de reserva y que si se ha agotado este procedimiento será inútil. El comando es el siguiente:

# smartctl -a /dev/sda | grep -i reallocated
5 Reallocated_Sector_Ct 0x0033 100 100 036 Pre-fail Always - 0

Si nos fijamos en el último dato, vemos que está a cero, lo que indica que nunca se han relocalizado sectores en el disco. En el ejemplo del artículo anterior, la cuenta estaba en 10640, una mala noticia sin duda.

El siguiente paso es confirmar que el supuesto sector defectuoso tiene realmente problemas de lectura. Siguiendo en el ejemplo del otro artículo, el comando es como sigue:

# hdparm --read-sector 2307480536 /dev/sda

/dev/sda:
reading sector 2307480536: FAILED: Input/output error

Efectivamente, el sector es defectuoso, así que podemos proceder a relocalizarlo:

# hdparm --write-sector 2307480536 /dev/sda

/dev/sda:
Use of --write-sector is VERY DANGEROUS.
You are trying to deliberately overwrite a low-level sector on the media
This is a BAD idea, and can easily result in total data loss.
Please supply the --yes-i-know-what-i-am-doing flag if you really want this.
Program aborted.

# hdparm --write-sector 2307480536 --yes-i-know-what-i-am-doing /dev/sda

/dev/sda: re-writing sector 2307480536: succeeded

Como comentaba más arriba, hdparm nos avisa de que se trata de una operación peligrosa porque estamos escribiendo en el disco duro a bajo nivel saltándonos los mecanismos estándares de escritura de bloques del sistema de ficheros residente.

Si la operación anterior tiene éxito, podemos comprobar el resultado:

# hdparm --read-sector 2307480536 /dev/sda

/dev/sda:
reading sector 2307480536: succeeded
0000 0000 0000 0000 0000 0000 0000 0000
...
(siguen muchas líneas con ceros a continuación)

# smartctl -a /dev/sda | grep -i reallocated
5 Reallocated_Sector_Ct 0x0033 100 100 036 Pre-fail Always - 1

Vemos que el sector vuelve a estar disponible para su uso y que la cuenta de sectores relocalizados ha aumentado en uno.

Ahora sólo es cuestión de decidir si seguimos con el disco adelante, lo reutilizamos para datos menos importantes o lo tiramos a la basura directamente.