Volver a vincular un archivo eliminado

33

A veces las personas eliminan archivos que no deberían, un proceso de larga duración todavía tiene el archivo abierto, y recuperar los datos mediante captura /proc/<pid>/fd/Nno es lo suficientemente impresionante. Lo suficientemente impresionante sería si pudiera "deshacer" la eliminación ejecutando alguna opción mágica en ln que le permitiera volver a vincular al número de inodo (recuperado a través de lsof).

No puedo encontrar ninguna herramienta de Linux para hacer esto, al menos con Google superficial.

¿Qué tienes, serverfault?

EDITAR1: La razón por la que capturar el archivo /proc/<pid>/fd/Nno es lo suficientemente impresionante es porque el proceso que todavía tiene el archivo abierto todavía le está escribiendo. Una eliminación elimina la referencia al inodo del espacio de nombres del sistema de archivos. Lo que quiero es una forma de recrear la referencia.

EDIT2: 'debugfs ln' funciona, pero el riesgo es demasiado alto, ya que afecta a los datos sin procesar del sistema de archivos. El archivo recuperado también es loco inconsistente. El recuento de enlaces es cero y no puedo agregarle enlaces. Estoy peor de esta manera ya que solo puedo usar /proc/<pid>/fd/Npara acceder a los datos sin corromper mi fs.

mbac32768
fuente

Respuestas:

14

Lo suficientemente impresionante sería si pudiera "deshacer" la eliminación ejecutando alguna opción mágica en ln que le permitiera volver a vincular al número de inodo (recuperado a través de lsof).

Esta genialidad se introdujo lnen v8.0 (GNU / coreutils) con la -L|--logicalopción que hace lnque /proc/<pid>/fd/<handle>primero se elimine la referencia . Entonces un simple

ln -L /proc/<pid>/fd/<handle> /path/to/deleted/file

es suficiente para volver a vincular un archivo eliminado.

tnimeu
fuente
77
Esto no funciona Si se elimina el archivo, fallará.
Random832
1
No, no lo hará. Regularmente uso esto para restaurar archivos borrados pero aún abiertos. Pero debe asegurarse de que el nuevo /path/to/deleted/fileesté en el mismo sistema de archivos que el archivo justo antes de que se elimine, de lo contrario, esto fallará. (Puede obtener el viejo camino con ls -l /proc/<pid>/fd/<handle>)
tnimeu
2
Este tipo de funcionalidad (consulte esta pregunta y respuesta) fue rechazada específicamente como un riesgo de seguridad [para un esquema de seguridad hipotético que gira en torno a un proceso privilegiado que le da a su proceso un identificador de archivo de solo lectura para un archivo que posee pero que de otra manera no tiene acceso a ]; Lo intenté (aunque con un pequeño programa en C para usar directamente la llamada al sistema relevante) y no funcionó.
Random832
77
Yo, por supuesto, probé esto antes de publicar mi solución y en ese momento realmente funcionó para mí. Lo que no sabía es que solo funcionaba en tmpfssistemas de archivos, pero no en eg ext3. Además, esta característica se deshabilitó por completo en 2.6.39, consulte la confirmación . Por lo tanto, esta solución ya no funcionará con el kernel 2.6.39 o más reciente y en versiones anteriores depende del sistema de archivos.
tnimeu
77
@tnimeu ln -Lno funciona para mí. Tengo un archivo eliminado e intenté volver a vincularlo a la ruta original. lnMe da una ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory. Pero puedo, por ejemplo, con éxitocat /proc/19674/fd/16
Eugene Beresovsky
13

Parece que ya entiendes mucho, así que no entraré en detalles excesivos. Hay varios métodos para encontrar el inodo y, por lo general, puede detectar y redirigir STDOUT. Puedes usardebugfs . Ejecute este comando dentro de:

ln <$INODE> FILENAME

Asegúrese de tener copias de seguridad del sistema de archivos. Probablemente necesitarás ejecutar un fsck después. Probé esto con éxito con un inodo aún escrito y funciona para crear un nuevo enlace duro a un inodo desreferenciado.

Si el archivo está desvinculado con un archivo sin abrir en ext3, los datos se pierden. No estoy seguro de cuán consistentemente cierto es esto, pero la mayor parte de mi experiencia de recuperación de datos es con ext2. De las preguntas frecuentes ext3:

P: ¿Cómo puedo recuperar (recuperar) archivos borrados de mi partición ext3? En realidad, no puedes! Esto es lo que uno de los desarrolladores, Andreas Dilger, dijo al respecto:

Para garantizar que ext3 pueda reanudar de forma segura un desvinculación después de un bloqueo, en realidad elimina los punteros de bloque en el inodo, mientras que ext2 simplemente marca estos bloques como no utilizados en los mapas de bits del bloque y marca el inodo como "eliminado" y deja el bloque punteros solos.

Su única esperanza es "grep" para partes de sus archivos que se han eliminado y esperar lo mejor.

También hay información relevante en esta pregunta:

Sobreescribí un archivo grande con uno en blanco en un servidor Linux. ¿Puedo recuperar el archivo existente?

Warner
fuente
Comentario con suerte borrado ya que no fue revelador.
mdpc
1
En el caso de un archivo eliminado pero aún abierto, no creo que ponga a cero los punteros en el inodo. Además, en lugar de usar "ln" en debugfs, usaría "undel" para que los recuentos de referencia de inodo se actualicen correctamente.
Mark Wagner
No quise aludir como tal, embobo. No es así, probé el rendimiento. He aclarado mi lenguaje.
Warner
Inteligente, pero corrompe mi sistema de archivos. :)
mbac32768
Es la única solución para el escenario tal como lo describe. La manipulación de un sistema de archivos en un nivel bajo que está montado en rw y en el que se está escribiendo activamente es probable que cause corrupción en casi todos los escenarios.
Warner
8

la forma de depuración como viste realmente no funciona y, en el mejor de los casos, tu archivo se eliminará automáticamente (debido al diario) después del reinicio y, en el peor de los casos, puedes destruir tu sistema de archivos como resultado del "ciclo de reinicio de la muerte". La solución correcta (TM) es realizar la recuperación en el nivel VFS (que también tiene el beneficio adicional de trabajar con prácticamente todos los sistemas de archivos Linux actuales). La forma de llamada del sistema (parpadeo) se ha desactivado cada vez que apareció en LKML, por lo que la mejor manera es a través de un módulo + ioctl.

Un proyecto que implementa este enfoque y tiene un código razonablemente pequeño y limpio es fdlink ( https://github.com/pkt/fdlink.git para una versión probada con el núcleo de ubuntu maverick). Con él, después de insertar el módulo (sudo insmod flink_dev.ko) puede hacer "./flinkapp / proc // fd / X / my / link / path" y hará exactamente lo que desea.

También puede usar una versión de vfs-undelete.sourceforge.net portada hacia adelante que también funciona (y también puede volver a vincular automáticamente al nombre original), pero el código de fdlink es más simple y funciona igual de bien, por lo que es mi preferencia.

pktoss
fuente
3

No sé cómo hacer exactamente lo que quieres, pero lo que haría es:

  • Abra el archivo RO desde otro proceso
  • Espere a que salga el proceso original
  • Copie los datos de su FD abierto a un archivo

No es ideal, obviamente, pero es posible. La otra opción es jugar con debugfs (usando el linkcomando), ¡pero eso da miedo en una máquina de producción!

Bill Weiss
fuente
El comando de enlace debugfs no es compatible con este caso de uso.
mbac32768
tldp.org/HOWTO/Ext2fs-Undeletion-11.html sugiere que sí. No lo he probado, pero eso parece razonable.
Bill Weiss
linkno funcionó en mis pruebas pero lo lnhizo.
Warner
3

Me encontré con el mismo problema hoy. Lo mejor que se me ocurre es correr

% tail -n +0 -f /proc/<pid>/fd/<fd> /path/to/deleted_file

en una sesión tmux / screen hasta que finalice el proceso.

nickray
fuente
2
Vincular a los archivos originales, como en la respuesta aceptada, debería funcionar.
Chris S
1
No hay una respuesta aceptada para esta pregunta, ¿a cuál se refiere?
Hamman Samuel
¿No debería esto necesitar una redirección ( >) al archivo eliminado?
ncasas
1

Interesante pregunta. Un entrevistador me hizo la misma pregunta en una entrevista de trabajo. Lo que le dije fue que no había una manera fácil de hacer esto y, en general, no valía la pena el tiempo y el esfuerzo involucrados. Le pregunté cuál creía que era la solución a este problema ...

  1. Use lsof para encontrar el número de inodo en el disco para el proceso, ya que aún aparecerá incluso si el archivo se ha eliminado ... la clave es que todavía está abierto.
  2. Extraiga la información del sistema de archivos basándose en esto a través de un depurador del sistema de archivos.
mdpc
fuente
Puedo extraer los datos bien de / proc / <pid> / fd / N pero eso no es lo que estoy tratando de hacer.
mbac32768
1

Utilice Sleuthkit icat.

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file
Isaac
fuente
Esto funciona pasando por alto la funcionalidad del sistema de archivos del sistema operativo y analizando los bytes del disco directamente.
Flimm
0

La solución rápida que funcionó para mí, sin herramientas intimidantes:

1) encuentre el proceso + fd mirando directamente en / proc:

ls -al /proc/*/fd/* 2>/dev/null | grep {filename}

2) Luego, una técnica similar a la de @ nickray, con pv:

tail -c +0 -f /proc/{procnum}/fd/{fdnum} | pv -s {expectedsize} > {recovery_filename}

Es posible que necesite Ctrl-C cuando termine ( ls /proc/{procnum}/fd/{fdnum}le indicará que el archivo ya no existe), pero si conoce el tamaño exacto en bytes, puede usarlo pv -Spara que salga cuando se alcance el recuento.

xenoide
fuente