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.