Come recuperare il file cancellato se è ancora aperto da qualche processo?


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)

Come recuperarlo important_file?

Ho provato qualcosa del genere

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

ma non fa nulla.

Risposte:


11

Se / home è NFS, ci sarà un file .nfsNNNNNNNNNN in / home / vi a cui puoi accedere / copiare. Se home è un filesystem locale, dovresti essere in grado di fare la stessa cosa tramite il link / proc / PID / fd / 3:

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

Se vuoi effettivamente ripristinare il file, ecco un post sul blog sull'argomento.


1
OK, ne ero confuso readlink /proc/13381/fd/3-> "/ home / vi / important_file (cancellato)" e /home/vi/important_file\ \(deleted\)ovviamente non esiste.
Vi.

22

... meglio che copiare in un dato momento (e raccogliere solo l'istantanea di quel tempo del contenuto del file) è " tail -f" quel file in un nuovo file:

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

(grazie ai cauti programmatori di tail, funzionerà anche con output binario.)

Durante il suo runtime, lo tail -fstesso mantiene aperto il file, impedendo in modo sicuro di essere rimosso dal disco quando termina il programma originale. Quindi, non fermarti tail -fsubito dopo la fine del programma originale: controlla /new/path/to/fileprima la coda se è quello che vuoi. Se non lo è (o è insoddisfacente per qualsiasi altro motivo), è possibile copiare nuovamente il file originale, ma questa volta dopo tutto la scrittura su di esso è terminata da "Programma" e dalla tail -f/ proc / PIDoftail / ancora in esecuzione directory fd /.


3
Che ne dici di creare un hardlink a / proc / PIDofProgram> / fd / #?
becko,

2
@becko Invalid cross-device link.
Kamil Maciorowski,

10

Utilizzare lsof per trovare il numero di inode e debugfs per ricreare un collegamento reale ad esso. Per esempio:

# 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

Prima che tu ti lamenti, ho falsificato la trascrizione sopra poiché non ho un file eliminato a portata di mano in questo momento ;-)

Io uso mi per ripristinare il tempo di eliminazione e il conteggio dei collegamenti su valori sensibili (rispettivamente 0 e 1), ma non funziona correttamente - è possibile vedere che il conteggio dei collegamenti rimane a zero in ls. Penso che il kernel potrebbe memorizzare nella cache i dati dell'inode. Probabilmente dovresti fsck alla prima opportunità dopo aver usato debugfs, per essere al sicuro.

Nella mia esperienza, è necessario creare il collegamento utilizzando un nome file temporaneo e quindi rinominarlo con il nome corretto. Il collegamento diretto al nome del file originale sembra causare il danneggiamento della directory. YMMV!


Perché lo stai suggerendo esattamente se non funziona davvero correttamente e causa danni al sistema? Penso che dovresti avere un disclaimer più vivido nella risposta che questo è semplicemente un WiP, e non dovrebbe davvero essere provato in produzione.
primo

3

Puoi solo cpil file, ovvero:

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

Ovviamente, se il file è ancora in fase di modifica, incontrerai problemi con questo approccio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.