¿Cómo recuperar el archivo eliminado si aún está abierto por algún proceso?

19
$ cat important_file > /dev/null &
[1] 9711
$ rm important_file 
$ killall -STOP cat

[1]+  Stopped                 cat important_file > /tmp/p
$ ls -l /proc/`pidof cat`/fd/
total 0
lrwx------ 1 vi vi 64 May 13 20:32 0 -> /dev/pts/29
l-wx------ 1 vi vi 64 May 13 20:32 1 -> /tmp/p
lrwx------ 1 vi vi 64 May 13 20:32 2 -> /dev/pts/29
lr-x------ 1 vi vi 64 May 13 20:32 3 -> /home/vi/important_file (deleted)

¿Cómo recuperar esto important_file?

Intenté algo como

injcode -m dup2 -ofd=3 -ofilename=/tmp/recovered_file -oflags=O_CREAT $PID_OF_CAT

Pero no hace nada.

Vi.
fuente

Respuestas:

11

Si / home es NFS, habrá un archivo .nfsNNNNNNNNNN en / home / vi al que puede acceder / copiar. Si home es un sistema de archivos local, debería poder hacer lo mismo a través del enlace / proc / PID / fd / 3:

cp /proc/PID/fd/3 /tmp/recovered_file

Si realmente desea recuperar el archivo, aquí hay una publicación de blog sobre el tema.

Mark Johnson
fuente
1
OK, estaba confundido por eso readlink /proc/13381/fd/3-> "/ home / vi / important_file (eliminado)" y /home/vi/important_file\ \(deleted\)obviamente no existe.
Vi.
22

... mejor que copiar en un momento dado (y reunir solo la instantánea del contenido del archivo) es " tail -f" ese archivo en un archivo nuevo:

tail -c +0 -f /proc/PIDofProgram>/fd/# > /new/path/to/file

(gracias a los programadores cautelosos de tail, eso incluso funcionará con salida binaria).

Durante su tiempo de ejecución, el tail -fmismo mantiene el archivo abierto, evitando de forma segura que se purgue del disco cuando finaliza el programa original. Por lo tanto, no detenga el programa tail -finmediatamente después de que finalice su programa original; compruebe /new/path/to/fileprimero si es lo que desea. Si no lo es (o es insatisfactorio por cualquier otro motivo), puede copiar el archivo original nuevamente, pero esta vez después de que toda la escritura haya terminado por "Programa" y desde el tail -f/ s / proc / PIDoftail / aún en ejecución directorio fd /.

cristiano
fuente
3
¿Qué pasa con la creación de un enlace duro a / proc / PIDofProgram> / fd / #?
Becko
2
@becko Invalid cross-device link.
Kamil Maciorowski
10

Use lsof para encontrar el número de inodo y debugfs para recrear un enlace rígido a él. Por ejemplo:

# lsof -p 12345 | grep /var/log/messages
syslogd 12345 root    3w   REG                8,3    3000    987654 /var/log/messages (deleted)
# mount | grep var
/dev/sda2 on /var type ext3 (rw)
# debugfs -w /dev/sda2
debugfs: cd log
debugfs: ln <987654> tmp
debugfs: mi tmp
                      Mode    [0100600] 
                   User ID    [0] 
                  Group ID    [0] 
                      Size    [3181271] 
             Creation time    [1375916400] 
         Modification time    [1375916322] 
               Access time    [1375939901]
             Deletion time    [9601027] 0
                Link count    [0] 1
               Block count    [6232] 
                File flags    [0x0] 
...snip...
debugfs:  q
# mv /var/log/tmp /var/log/messages
# ls -al /var/log/messages
-rw------- 0 root root 3301 Aug  8 10:10 /var/log/messages

Antes de quejarse, falsifiqué la transcripción anterior ya que no tengo un archivo eliminado en este momento ;-)

Utilizo mipara restablecer el tiempo de eliminación y el recuento de enlaces a valores razonables (0 y 1 respectivamente), pero no funciona correctamente: puede ver que el recuento de enlaces permanece en cero ls. Creo que el núcleo podría estar almacenando en caché los datos del inodo. Probablemente debería fsck lo antes posible después de usar debugfs, para estar seguro.

En mi experiencia, debe crear el enlace con un nombre de archivo temporal y luego cambiar el nombre por el nombre correcto. Vincularlo directamente al nombre del archivo original parece causar daños en el directorio. YMMV!

Andrew Gallagher
fuente
¿Por qué exactamente sugieres esto si realmente no funciona correctamente y causa daños al sistema? Creo que debería tener un descargo de responsabilidad más vívido en la respuesta de que esto es simplemente un WiP, y realmente no debería probarse en producción.
Cnst
3

Puede simplemente cpel archivo, es decir:

cp /proc/<pid>/fd/<fdno> /new/path/to/file

Por supuesto, si el archivo aún se está modificando, tendrá problemas con este enfoque.

ninjalj
fuente