Ricollegare un file eliminato


33

A volte le persone eliminano i file che non dovrebbero, un processo di lunga durata ha ancora il file aperto e il recupero dei dati catting /proc/<pid>/fd/Nnon è abbastanza eccezionale. Sarebbe davvero fantastico se tu potessi "annullare" l'eliminazione eseguendo qualche opzione magica su ln che ti consentirebbe di ricollegarti al numero di inode (recuperato tramite lsof).

Non riesco a trovare alcun strumento Linux per fare questo, almeno con Google Google.

Che cosa hai, serverfault?

EDIT1: Il motivo per cui catturare il file /proc/<pid>/fd/Nnon è abbastanza eccezionale è perché il processo che ha ancora il file aperto sta ancora scrivendo su di esso. Una cancellazione rimuove il riferimento all'inode dallo spazio dei nomi del filesystem. Quello che voglio è un modo per ricreare il riferimento.

EDIT2: 'debugfs ln' funziona ma il rischio è troppo alto poiché blocca i dati grezzi del filesystem. Il file recuperato è anche pazzo incoerente. Il conteggio dei collegamenti è zero e non riesco ad aggiungere collegamenti ad esso. Sto peggio in questo modo poiché posso semplicemente usare /proc/<pid>/fd/Nper accedere ai dati senza corrompere il mio fs.

Risposte:


14

Sarebbe davvero fantastico se tu potessi "annullare" l'eliminazione eseguendo qualche opzione magica su ln che ti permetterebbe di ricollegarti al numero di inode (recuperato tramite lsof).

Questa meraviglia è stata introdotta lnin v8.0 (GNU / coreutils) con l' -L|--logicalopzione che provoca lnuna /proc/<pid>/fd/<handle>prima deduzione . Quindi un semplice

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

è sufficiente per ricollegare un file eliminato.


7
Questo non funziona; se il file viene eliminato, fallirà.
Casuale 832

1
No, non lo farà. Lo uso regolarmente per ripristinare file cancellati ma ancora aperti. Ma devi assicurarti che il nuovo /path/to/deleted/filesia sullo stesso filesystem del file appena prima dell'eliminazione, altrimenti fallirà. (È possibile ottenere il vecchio percorso con ls -l /proc/<pid>/fd/<handle>)
tnimeu

2
Questo tipo di funzionalità (Vedi questa domanda e risposta) è stata specificamente respinta come un rischio per la sicurezza [per un ipotetico schema di sicurezza che ruota attorno a un processo privilegiato, dando al tuo processo un handle di file di sola lettura per un file che possiedi ma che altrimenti non ha accesso a ]; L'ho provato (anche se con un piccolo programma C per utilizzare direttamente la chiamata di sistema pertinente) e non ha funzionato.
Casuale 832

7
Naturalmente, l'ho provato prima di pubblicare la mia soluzione e in quel momento ha funzionato per me. Ciò di cui non ero a conoscenza è che ha funzionato solo su tmpfsfilesystem ma non su es ext3. Inoltre, questa funzione è stata completamente disabilitata in 2.6.39, vedere il commit . Quindi questa soluzione non funzionerà più con il kernel 2.6.39 o più recente e nelle versioni precedenti dipende dal filesystem.
tnimeu,

7
@tnimeu ln -Lnon funziona per me. Ho un file cancellato e ho provato a ricollegarlo al percorso originale. lnmi dà un ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory. Ma posso ad es. Con successocat /proc/19674/fd/16
Eugene Beresovsky,

13

Sembra che tu abbia già capito molto, quindi non entrerò nei dettagli in eccesso. Esistono diversi metodi per trovare l'inode e di solito puoi cat e reindirizzare STDOUT. È possibile utilizzare debugfs. Esegui questo comando in:

ln <$INODE> FILENAME

Assicurati di disporre di backup del filesystem. Probabilmente dovrai eseguire un fsck in seguito. L'ho testato con successo con un inode ancora in fase di scrittura e funziona per creare un nuovo collegamento reale a un inode con riferimenti.

Se il file non è collegato con un file non aperto in ext3, i dati vengono persi. Non sono sicuro di quanto sia sempre vero, ma la maggior parte della mia esperienza di recupero dati è con ext2. Dalle FAQ ext3:

D: Come posso recuperare (ripristinare) i file cancellati dalla mia partizione ext3? In realtà, non puoi! Questo è quanto ha affermato uno degli sviluppatori, Andreas Dilger:

Al fine di garantire che ext3 possa riprendere in modo sicuro un unlink dopo un crash, in realtà azzera i puntatori di blocco nell'inode, mentre ext2 contrassegna questi blocchi come inutilizzati nelle bitmap del blocco e contrassegna l'inode come "eliminato" e lascia il blocco solo puntatori.

La tua unica speranza è quella di "grep" per parti dei tuoi file che sono stati eliminati e sperare per il meglio.

Ci sono anche informazioni rilevanti in questa domanda:

Ho sovrascritto un file di grandi dimensioni con uno vuoto su un server Linux. Posso recuperare il file esistente?


Speriamo che il commento sia stato eliminato in quanto non è stato rivelato.
mdpc,

1
Nel caso di un file cancellato ma ancora aperto, non credo che azzererebbe i puntatori nell'inode. Inoltre, invece di usare "ln" in debugfs, userei "undel" in modo che i conteggi dei riferimenti agli inode vengano aggiornati correttamente.
Mark Wagner,

Non intendevo alludere come tale, embobo. No, ho testato le prestazioni. Ho chiarito la mia lingua.
Warner,

Intelligente, ma corrompe il mio filesystem. :)
mbac32768

È l'unica soluzione per lo scenario mentre lo descrivi. La manipolazione di un filesystem a basso livello su cui è montato rw e su cui si sta scrivendo attivamente potrebbe causare danni in quasi tutti gli scenari.
Warner,

8

il modo di debug come hai visto non funziona davvero e nella migliore delle ipotesi il tuo file verrà eliminato automaticamente (a causa del journal) dopo il riavvio e nella peggiore delle ipotesi puoi eliminare il tuo filesystem risultante in "riavvio del ciclo della morte". La soluzione giusta (TM) è quella di eseguire il ripristino nel livello VFS (che ha anche il vantaggio di lavorare praticamente con tutti i filesystem Linux attuali). Il modo di chiamata di sistema (flink) è stato abbattuto ogni volta che è apparso in LKML, quindi il modo migliore è attraverso un modulo + ioctl.

Un progetto che implementa questo approccio e ha un codice ragionevolmente piccolo e pulito è fdlink ( https://github.com/pkt/fdlink.git per una versione testata con il kernel di Ubuntu Maverick). Con esso, dopo aver inserito il modulo (sudo insmod flink_dev.ko) puoi semplicemente fare "./flinkapp / proc // fd / X / my / link / path" e farà esattamente quello che vuoi.

Puoi anche usare una versione con port forwarding di vfs-undelete.sourceforge.net che funziona (e può anche ricollegarsi automaticamente al nome originale), ma il codice di fdlink è più semplice e funziona altrettanto bene, quindi è la mia preferenza.


3

Non so come fare esattamente quello che vuoi, ma quello che vorrei fare è:

  • Apri il file RO da un altro processo
  • Attendere il termine del processo originale
  • Copia i dati dall'FD aperto in un file

Non ideale, ovviamente, ma possibile. L'altra opzione è quella di giocare con debugfs (usando il linkcomando), ma è un po 'spaventoso su una macchina di produzione!


Il comando debugfs link non supporta affatto questo caso d'uso.
mbac32768

tldp.org/HOWTO/Ext2fs-Undeletion-11.html suggerisce che lo fa. Non l'ho provato, ma sembra ragionevole.
Bill Weiss,

linknon ha funzionato nei miei test ma lnha funzionato.
Warner,

3

Ho incontrato lo stesso problema oggi. Il meglio che ho potuto inventare è correre

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

in una sessione tmux / screen fino al termine del processo.


2
Il collegamento ai file originali, come nella risposta accettata, dovrebbe funzionare.
Chris S,

1
Non esiste una risposta accettata per questa domanda, a quale ti riferisci?
Hamman Samuel,

Non dovrebbe essere necessario un reindirizzamento ( >) al file eliminato?
ncasas,

1

Domanda interessante. Un intervistatore mi ha posto la stessa domanda in un colloquio di lavoro. Quello che gli ho detto è che non c'era un modo semplice per farlo e in generale non valeva il tempo e gli sforzi necessari. Gli ho chiesto quale pensava fosse la soluzione a questo problema ...

  1. Usa lsof per trovare il numero di inode sul disco per il processo in quanto verrà visualizzato anche se il file è stato eliminato ... la chiave è che è ancora aperto.
  2. Estrarre le informazioni dal filesystem in base a ciò tramite un debugger del filesystem.

Posso estrarre i dati bene da / proc / <pid> / fd / N ma non è quello che sto cercando di fare.
mbac32768

1

Usa Sleuthkit icat.

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file

Funziona bypassando la funzionalità del filesystem del sistema operativo e analizzando direttamente i byte del disco.
Flimm,

0

La soluzione rapida che ha funzionato per me, senza strumenti intimidatori:

1) trova il processo + fd guardando direttamente in / proc:

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

2) Quindi una tecnica simile a quella di @ nickray, con l'aggiunta di pv:

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

Al termine potrebbe essere necessario Ctrl-C ( ls /proc/{procnum}/fd/{fdnum}ti dirà che il file non esiste più)), ma se conosci la dimensione esatta in byte, puoi usarlo pv -Sper uscire quando viene raggiunto il conteggio.

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.