Durch eine unglueckliche Konstellation kam es dazu, dass mir von laufenden, produktiven, KVM Maschinen die Images abhanden kamen. Kurzum: Gelöscht. Aber da die Maschinen noch liefen eine gute Gelegenheit sich an der Rettung zu versuchen, und nicht über ein Backup zu arbeiten.
Dadurch, dass die Datei Images noch in Benutzung waren, war ein File-Handle mit dem jeweiligen Prozess verknüpft. Dieser kann nach Belieben noch mit der Datei arbeiten, auch das Dateisystem betrachtet die zu der Datei gehörenden Datenblöcke nicht als frei und bewahrt sie somit vor Verlust. Solange der Prozess läuft aber nur.

Zur Illustration verwenden wir einmal folgende Kommandos:

wget --limit-rate=1000 http://releases.ubuntu.com/14.04/ubuntu-14.04-desktop-amd64.iso

Der Download ist extra langsam gedreht, so dass genug Zeit ist zum experimentieren.
Nun loeschen wir die Datei – das wget laeuft weiter.

rm ubuntu-14.04-desktop-amd64.iso

Suchen wir nun nach Prozessen, die auf gelöschte Dateien zugreifen und filtern nach Dateien mit dem Wort „ubuntu“:

lsof | grep deleted | grep ubuntu
wget 10694 tkruse 4w REG 252,1 195943 1573596 /home/tkruse/ubuntu-14.04-desktop-amd64.iso (deleted)

Der einfachste Weg den Inhalt zu retten wäre nun, einfach die Datei(inhalte) zu kopieren. Dazu suchen wir das Filehandle des Prozesses „10694“ (dem wget aus dem lsof)


ls -l /proc/10694/fd             
total 0
lrwx------ 1 tkruse tkruse 64 Jul 12 13:02 0 -> /dev/pts/7
lrwx------ 1 tkruse tkruse 64 Jul 12 13:02 1 -> /dev/pts/7
lrwx------ 1 tkruse tkruse 64 Jul 12 13:02 2 -> /dev/pts/7
lrwx------ 1 tkruse tkruse 64 Jul 12 13:02 3 -> socket:[797560]
l-wx------ 1 tkruse tkruse 64 Jul 12 13:02 4 -> /home/tkruse/ubuntu-14.04-desktop-amd64.iso.1 (deleted)

Das Datei handle können wir als Quelle nehmen, und den Inhalt nun kopieren:

cp /proc/10694/fd/4 /home/tkruse/rescue

Da die Maschinen noch laufen, wäre es eigentlich schön nicht einen Zustand zu kopieren, sondern die Datei auf ’nicht gelöscht‘ setzen zu können. Das ging mal mit ln -L, wurde jedoch aus Sicherheitsgründen aus dem Kernel entfernt.

Dazu kann man nur noch direkt ins Dateisystem eingreifen. Nichts für Angsthasen – und ein fsck sollte danach besser stattfinden.
Mittels debugfs kann man einen neuen Link auf die inode der Datei anlegen. Darüber kann danach wieder ein Zugriff erfolgen. Jedoch wird dabei der Link-Count nicht erhöht, so dass die Datei nicht wirklich wieder hergestellt ist.
Die inode ist die Zahl aus dem lsof vor dem Dateipfad, in diesem Fall „1573596“. Legen wir also eine neue Datei an, die diese inode nutzt:

sudo debugfs -w /dev/mapper/ubuntu--gnome--vg-root -R "link <1573596> rescue"

Anschließend kann man den Prozess, der die Datei bisher noch offen und damit am Leben gehalten hat, beenden und die Datei (auf ein anderes Dateisystem) kopieren.

cp rescue ....

Ist man damit fertig, kann man den Link wieder aufheben.

sudo debugfs -w /dev/mapper/ubuntu--gnome--vg-root -R "unlink rescue"

Durch durch das debugfs ist es im Prinzip auch möglich den Linkcount zu reparieren, das war mir jedoch etwas zu warm. Auch bin ich nicht sicher, wie es sich mit dem „gelöscht“ Flag tatsächlich verhält, so dass ich die Daten dann auf ein anderes Dateisystem kopiert habe (um versehentliches überschreiben zu verhindern), das betroffene Dateisystem ausgehängt und per fsck geprüft habe.
Soweit ich das beurteilen kann: Die Datei wurde perfekt gerettet und alles läuft mit minimaler Downtime weiter.