Erneutes Verknüpfen einer gelöschten Datei

33

Manchmal löschen Leute Dateien, die sie nicht löschen sollten. Bei einem langen Prozess ist die Datei immer noch geöffnet, und das Wiederherstellen der Daten durch Catting ist /proc/<pid>/fd/Neinfach nicht großartig genug. Genial genug wäre, wenn Sie das Löschen "rückgängig machen" könnten, indem Sie eine magische Option ausführen, mit der Sie sich wieder mit der Inode-Nummer verbinden können (wiederhergestellt durch lsof).

Ich kann keine Linux-Tools finden, um dies zu tun, am wenigsten mit flüchtigem Googeln.

Was hast du, Serverfehler?

EDIT1: Der Grund, warum das Catting der Datei /proc/<pid>/fd/Nnicht großartig genug ist, ist, dass der Prozess, bei dem die Datei noch geöffnet ist, noch in die Datei schreibt. Beim Löschen wird der Verweis auf den Inode aus dem Namespace des Dateisystems entfernt. Was ich möchte, ist eine Möglichkeit, die Referenz neu zu erstellen.

EDIT2: 'debugfs ln' funktioniert, aber das Risiko ist zu hoch, da es rohe Dateisystemdaten frobs. Die wiederhergestellte Datei ist auch verrückt inkonsistent. Die Linkanzahl ist Null und ich kann keine Links hinzufügen. Mir geht es auf diese Weise schlechter, da ich nur /proc/<pid>/fd/Nauf die Daten zugreifen kann, ohne meine fs zu beschädigen.

mbac32768
quelle

Antworten:

14

Genial genug wäre, wenn Sie das Löschen "rückgängig machen" könnten, indem Sie eine magische Option ausführen, mit der Sie sich wieder mit der Inode-Nummer verbinden können (wiederhergestellt durch lsof).

Diese Besonderheit wurde lnin Version 8.0 (GNU / coreutils) mit der -L|--logicalOption eingeführt, die lneine /proc/<pid>/fd/<handle>erste Dereferenzierung bewirkt . So einfach

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

reicht aus, um eine gelöschte Datei erneut zu verknüpfen.

tnimeu
quelle
7
Das geht nicht; Wenn die Datei gelöscht wird, schlägt sie fehl.
Random832
1
Nein, das wird es nicht. Ich verwende dies regelmäßig, um gelöschte, aber noch geöffnete Dateien wiederherzustellen. Aber Sie müssen sicherstellen, dass das Neue /path/to/deleted/fileauf dem Laufenden ist Datei demselben Dateisystem befindet wie die Datei unmittelbar vor dem Löschen. Andernfalls schlägt dies in der Tat fehl. (Sie können den alten Pfad mit bekommen ls -l /proc/<pid>/fd/<handle>)
tnimeu
2
Diese Art von Funktionalität (Siehe diese Frage und Antwort) wurde ausdrücklich als Sicherheitsrisiko abgelehnt [für ein hypothetisches Sicherheitsschema, das sich um einen privilegierten Prozess dreht und Ihrem Prozess ein schreibgeschütztes Dateihandle für eine Datei verleiht, auf die Sie jedoch sonst keinen Zugriff haben ]; Ich habe es versucht (allerdings mit einem kleinen C-Programm, um den entsprechenden Systemaufruf direkt zu verwenden) und es hat nicht funktioniert.
Random832
7
Ich habe das natürlich getestet, bevor ich meine Lösung gepostet habe, und zu diesem Zeitpunkt hat es tatsächlich für mich funktioniert. Was mir nicht bewusst war, ist, dass es nur auf tmpfsDateisystemen funktioniert, aber nicht auf zB ext3. Außerdem wurde diese Funktion in 2.6.39 komplett deaktiviert, siehe Commit . Daher funktioniert diese Lösung nicht mehr mit Kernel 2.6.39 oder neuer und hängt in früheren Versionen vom Dateisystem ab.
Donnerstag,
7
@tnimeu ln -Lfunktioniert bei mir nicht. Ich habe eine gelöschte Datei und habe versucht, sie erneut mit dem ursprünglichen Pfad zu verknüpfen. lngibt mir eine ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory. Aber ich kann zB erfolgreichcat /proc/19674/fd/16
Eugene Beresovsky
13

Es hört sich so an, als würdest du schon viel verstehen, also werde ich nicht zu sehr ins Detail gehen. Es gibt verschiedene Methoden, um die Inode zu finden, und Sie können STDOUT normalerweise cat- und redirect-fähig machen. Sie können verwenden debugfs. Führen Sie diesen Befehl aus in:

ln <$INODE> FILENAME

Stellen Sie sicher, dass Sie Backups des Dateisystems haben. Du wirst wahrscheinlich danach ein fsck ausführen müssen. Ich habe dies erfolgreich mit einem Inode getestet, in den noch geschrieben wird, und es funktioniert, um eine neue feste Verknüpfung zu einem dereferenzierten Inode zu erstellen.

Wenn die Verknüpfung der Datei mit einer nicht geöffneten Datei in ext3 aufgehoben wird, gehen die Daten verloren. Ich bin mir nicht sicher, wie konsequent dies ist, aber der größte Teil meiner Datenwiederherstellungserfahrung ist mit ext2. Aus den ext3 FAQ:

F: Wie kann ich gelöschte Dateien von meiner ext3-Partition wiederherstellen (wiederherstellen)? Eigentlich kannst du nicht! Das hat einer der Entwickler, Andreas Dilger, dazu gesagt:

Um sicherzustellen, dass ext3 nach einem Absturz die Verknüpfung sicher wiederherstellen kann, werden die Blockzeiger im Inode auf Null gesetzt, während ext2 diese Blöcke in den Blockbitmaps nur als unbenutzt markiert und den Inode als "gelöscht" markiert und den Block verlässt Zeiger allein.

Ihre einzige Hoffnung ist, nach Teilen Ihrer gelöschten Dateien zu "greifen" und auf das Beste zu hoffen.

Es gibt auch relevante Informationen in dieser Frage:

Ich habe eine große Datei mit einer leeren auf einem Linux-Server überschrieben. Kann ich die vorhandene Datei wiederherstellen?

Warner
quelle
Kommentar hoffentlich gelöscht, da er nicht enthüllt wurde.
mdpc
1
Im Falle einer gelöschten, aber noch offenen Datei glaube ich nicht, dass sie die Zeiger in der Inode auf Null setzen würde. Anstatt "ln" in Debugfs zu verwenden, verwende ich "undel", damit die Anzahl der Inode-Verweise korrekt aktualisiert wird.
Mark Wagner
Ich wollte nicht so anspielen, embobo. Ich habe die Leistung getestet. Ich habe meine Sprache geklärt.
Warner
Clever, aber mein Dateisystem beschädigt. :)
mbac32768
Dies ist die einzige Lösung für das beschriebene Szenario. Das Manipulieren eines Dateisystems auf einer niedrigen Ebene, auf die rw geladen ist und auf die aktiv geschrieben wird, kann in fast allen Szenarien zu Beschädigungen führen.
Warner
8

Wie Sie gesehen haben, funktioniert das Debuggen nicht wirklich und im besten Fall wird Ihre Datei nach dem Neustart automatisch (aufgrund des Journals) gelöscht. Die richtige Lösung (TM) besteht darin, das Wiederherstellen in der VFS-Ebene durchzuführen (was auch den zusätzlichen Vorteil hat, mit praktisch allen aktuellen Linux-Dateisystemen zu arbeiten). Der Systemaufruf (flink) wurde jedes Mal abgeschossen, wenn er in LKML angezeigt wurde. Der beste Weg ist also ein Modul + ioctl.

Ein Projekt, das diesen Ansatz implementiert und relativ kleinen und sauberen Code enthält, ist fdlink ( https://github.com/pkt/fdlink.git für eine Version, die mit dem Kernel von Ubuntu Maverick getestet wurde). Nachdem Sie das Modul (sudo insmod flink_dev.ko) eingefügt haben, können Sie einfach "./flinkapp / proc // fd / X / mein / link / path" ausführen und es wird genau das tun, was Sie wollen.

Sie können auch eine vorwärts portierte Version von vfs-undelete.sourceforge.net verwenden, die ebenfalls funktioniert (und auch automatisch auf den ursprünglichen Namen zurückgreifen kann), aber der Code von fdlink ist einfacher und funktioniert genauso gut, also ist es meine Präferenz.

pktoss
quelle
3

Ich weiß nicht, wie ich genau das machen soll, was Sie wollen, aber was ich tun würde, ist:

  • Öffnen Sie die Datei RO aus einem anderen Prozess
  • Warten Sie, bis der ursprüngliche Vorgang beendet ist
  • Kopieren Sie die Daten von Ihrem geöffneten FD in eine Datei

Natürlich nicht ideal, aber möglich. Die andere Möglichkeit besteht darin, mit Debugfs (mit dem linkBefehl) herumzuspielen , aber das ist auf einer Produktionsmaschine beängstigend!

Bill Weiss
quelle
Der Befehl debugfs link unterstützt diesen Anwendungsfall überhaupt nicht.
mbac32768
tldp.org/HOWTO/Ext2fs-Undeletion-11.html schlägt vor, dass dies der Fall ist. Ich habe es nicht ausprobiert, aber das scheint vernünftig.
Bill Weiss
linkhat bei meinen Tests nicht funktioniert, hat es aber lngetan.
Warner
3

Bin heute auf dasselbe Problem gestoßen. Das Beste, was ich mir einfallen lassen kann, ist zu rennen

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

in einer tmux / screen-Sitzung, bis der Vorgang endet.

nickray
quelle
2
Das Verknüpfen mit den Originaldateien sollte wie in der akzeptierten Antwort funktionieren.
Chris S
1
Es gibt keine akzeptierte Antwort auf diese Frage, auf welche beziehen Sie sich?
Hamman Samuel
Sollte dies nicht eine Umleitung ( >) zu der gelöschten Datei benötigen ?
Ncasas
1

Interessante Frage. Ein Interviewer hat mir in einem Vorstellungsgespräch die gleiche Frage gestellt. Was ich ihm sagte, war, dass es keinen einfachen Weg gab, dies zu tun, und im Allgemeinen die damit verbundene Zeit und Mühe nicht wert war. Ich habe ihn gefragt, was seiner Meinung nach die Lösung für dieses Problem ist ...

  1. Verwenden Sie lsof, um die Inode-Nummer auf der Festplatte für den Vorgang zu finden, da diese auch dann angezeigt wird, wenn die Datei gelöscht wurde. Der Schlüssel ist, dass sie noch offen ist.
  2. Extrahieren Sie die darauf basierenden Informationen über einen Dateisystem-Debugger aus dem Dateisystem.
mdpc
quelle
Ich kann die Daten gut aus / proc / <pid> / fd / N extrahieren, aber das ist nicht das, was ich versuche.
mbac32768
1

Verwenden Sie Sleuthkit icat.

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file
Isaac
quelle
Dies funktioniert, indem die Dateisystemfunktionalität des Betriebssystems umgangen und die Festplattenbytes direkt analysiert werden.
Flimm
0

Die schnelle Lösung, die für mich ohne einschüchternde Werkzeuge funktioniert hat:

1) finde den Prozess + fd indem du direkt in / proc schaust:

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

2) Dann eine ähnliche Technik wie bei @ nickray, mit pveingeworfen:

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

Möglicherweise müssen Sie Strg-C drücken, wenn Sie fertig sind (dies ls /proc/{procnum}/fd/{fdnum}zeigt an, dass die Datei nicht mehr vorhanden ist). Wenn Sie jedoch die genaue Größe in Byte kennen, können Sie pv -Ssie beenden, sobald die Anzahl erreicht ist.

Magnet
quelle