Silinen bir dosyayı yeniden bağlama


33

Bazen insanlar, yapmamaları gereken dosyaları siler, uzun süredir devam eden bir işlem hala açık dosyadır ve verileri yakalayarak kurtarmak /proc/<pid>/fd/Nyeterli değildir. Yeterince müthiş, inn numarasına yeniden bağlanmanıza izin verecek bir sihir seçeneği çalıştırarak silme işlemini "geri alabilirseniz" olur (lsof aracılığıyla kurtarıldı).

Bunu yapmak için Linux araçlarını bulamıyorum, en azından lanetli Googling ile.

Neyin var, serverfault?

DÜZENLEME1: Dosyayı yakalamanın nedeni /proc/<pid>/fd/Nyeterince harika değil çünkü dosyayı hala açık olan işlem hala yazıyor. Silme, inode başvurusunu dosya sistemi ad alanından kaldırır. İstediğim şey referansı yeniden oluşturmanın bir yolu.

EDIT2: 'debugfs ln' çalışıyor ancak ham dosya sistemi verilerini donduğu için risk çok yüksek. Kurtarılan dosya da çılgın tutarsız. Bağlantı sayısı sıfır ve buna bağlantı ekleyemiyorum. Bu şekilde daha kötüyüm, çünkü /proc/<pid>/fd/Nfs'imi bozmadan verilere erişmek için kullanabiliyorum .

Yanıtlar:


14

Yeterince müthiş, inn numarasına (lsof aracılığıyla yeniden bağlandı) yeniden bağlanmanıza izin verecek bir sihir seçeneği çalıştırarak silmeyi "geri alabilmeniz" olur.

Bu harika özellikler tanıtıldı lniçinde v8.0 ile (GNU / coreutils) -L|--logicalneden olan seçeneği lnbir KQUEUE /proc/<pid>/fd/<handle>ilk. Çok basit

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

silinmiş bir dosyayı yeniden bağlamak için yeterlidir.


7
Bu işe yaramıyor; dosya silinirse başarısız olur.
Random832

1
Hayır olmaz. Bunu düzenli olarak silinmiş ancak hala açılmış dosyaları geri yüklemek için kullanıyorum. Ancak yeninin /path/to/deleted/file, dosya silinmeden hemen önceki dosya sistemi ile aynı olduğundan emin olmanız gerekir , aksi halde bu - aslında - başarısız olur. (Eski yolu ile alabilirsiniz ls -l /proc/<pid>/fd/<handle>)
tnimeu

2
Bu tür bir işlevsellik ( Bu soruya ve cevaba bakın ), özellikle [sahip olduğunuz bir dosyaya işlem için salt okunur bir dosya tanıtıcısı veren ayrıcalıklı bir işlem etrafında dönen bir varsayımsal güvenlik şemasına] bir güvenlik riski olarak özellikle reddedildi . ]; (İlgili sistem çağrısını doğrudan kullanmak için küçük bir C programında olsa da) denedim ve çalışmadı.
Random832

7
Elbette, çözümümü yayınlamadan önce bunu test ettim ve o zaman gerçekten benim için çalıştı. Farkında değildim, sadece tmpfsdosya sistemlerinde çalıştığını, ancak örneğin çalıştığını ext3. Ayrıca bu özellik tamamen 2.6.39 devre dışı bkz var işlemek . Bu nedenle, bu çözüm artık 2.6.39 veya daha yeni bir sürümle çalışmayacak ve daha önceki sürümlerde dosya sistemine bağlıdır.
tnimeu

7
@tnimeu ln -Lbenim için çalışmıyor. Silinen bir dosyam var ve dosyayı orijinal yola yeniden bağlamaya çalıştım. lnbana bir verir ln: failed to create hard link /my/path/file.pdf => /proc/19674/fd/16: No such file or directory. Ama başarılı bir şekilde örneğin yapabilirimcat /proc/19674/fd/16
Eugene Beresovsky

13

Anlaşılan çok şey anlıyorsunuz, bu yüzden fazla ayrıntıya girmeyeceğim. İnode'u bulmak için birkaç yöntem vardır ve genellikle STDOUT'u kedi ile yeniden yönlendirebilirsiniz. Kullanabilirsiniz debugfs. Bu komutu içinde çalıştırın:

ln <$INODE> FILENAME

Dosya sistemini yedeklediğinizden emin olun. Muhtemelen daha sonra bir fsck çalıştırmanız gerekecektir. Bunu, hala yazılmakta olan bir inode ile başarılı bir şekilde test ettim ve bir yönetilen inode için yeni bir sabit link oluşturmak için çalışıyor.

Dosya ext3'te açılmamış bir dosyayla bağlantısızsa, veriler kaybolur. Bunun ne kadar tutarlı olduğunu doğru bilmiyorum ama veri kurtarma deneyimimin çoğu ext2'de. Ext3 SSS'den:

S: Silinen dosyaları ext3 bölümümden nasıl kurtarabilirim (geri silebilirim)? Aslında yapamazsın! Geliştiricilerden biri olan Andreas Dilger’in söylediği şey buydu:

Ext3'ün bir çökmeden sonra bir bağlantıyı güvenli bir şekilde sürdürmesini sağlamak için, aslında inode içindeki blok işaretleyicileri sıfırlar, ext2 ise bu blokları blok bitmaplerinde kullanılmayan olarak işaretler ve inode'u "silinmiş" olarak işaretler ve bloğu terk eder işaretçiler yalnız.

Tek umudunuz, dosyalarınızın silinmiş kısımlarını "aşmak" ve en iyisini ummaktır.

Bu soruda ayrıca alakalı bilgiler var:

Linux sunucusundaki boş bir dosyanın üzerine yazdım. Mevcut dosyayı kurtarabilir miyim?


Yorum umarım olmadığı için silindi.
mdpc

1
Silinen ancak hala açık olan bir dosya olması durumunda, inode'daki göstergeleri sıfırlayacağını sanmıyorum. Ayrıca, debugfs'ta "ln" kullanmak yerine, inode referans sayımlarının doğru bir şekilde güncellenmesi için "undel" kullanırım.
Mark Wagner,

Öyle demek istemedim, embobo. Öyle değil, performansı test ettim. Dilimi netleştirdim.
Warner

Akıllıca, ancak dosya sistemimi bozuyor. :)
mbac32768

Tanımladığınız senaryo için tek çözüm bu. Dosya sisteminin düşük bir düzeye monte edilmesi ve etkin bir şekilde yazılması ve neredeyse tüm senaryolarda yolsuzluğa neden olması muhtemeldir.
Warner

8

gördüğünüz gibi debugfs yolu gerçekten işe yaramaz ve en iyi ihtimalle dosyanız yeniden başlatıldıktan sonra otomatik olarak silinir (dergi nedeniyle) ve en kötü ihtimalle dosya sisteminizi "ölüm döngüsünün yeniden başlatılması" ile sonuçlandırabilir. Doğru Çözüm (TM), geri alma işlemini VFS düzeyinde gerçekleştirmektir (aynı zamanda tüm Linux sürümleriyle pratik olarak çalışmanın yararına da sahiptir). Sistem çağrısı yolu (yanıp sönme), LKML'de göründüğü her zaman aşağıya vuruldu, bu nedenle en iyi yol + modülünden geçiyor.

Bu yaklaşımı uygulayan ve oldukça küçük ve temiz bir koda sahip olan bir proje fdlink'tir ( ubuntu maverick'in çekirdeği ile test edilmiş bir sürüm için https://github.com/pkt/fdlink.git ). Bununla beraber, modülü (sudo insmod flink_dev.ko) taktıktan sonra sadece "./flinkapp / proc // fd / X / my / link / path" işlemini yapabilirsiniz ve tam olarak ne istersen onu yapar.

Ayrıca ileride çalışan vfs-undelete.sourceforge.net'in ayrıca çalışan (ve aynı zamanda otomatik olarak orijinal isme de bağlanabilir) versiyonunu kullanabilirsiniz, ancak fdlink'in kodu daha basittir ve aynı zamanda benim tercihimdir.


3

Ne istersen onu nasıl yapacağımı bilmiyorum, ama benim yapacağım şey:

  • RO dosyasını başka bir işlemden aç
  • Orijinal işlemin çıkmasını bekleyin
  • Açık FD'nizden bir dosyaya veri kopyalayın

İdeal değil, açık, ama mümkün. Diğer seçenek debugfs ile oynamaktır ( linkkomutu kullanarak ), ama bu bir üretim makinesinde biraz korkutucu!


Debugfs link komutu bu kullanım durumunu desteklemiyor.
mbac32768

tldp.org/HOWTO/Ext2fs-Undeletion-11.html bunu önerir. Denemedim, ama bu makul görünüyor.
Bill Weiss

linktestlerimde işe yaramadı ama lnyaptı.
Warner

3

Bugün aynı soruna rastladım. Gelebildiğim en iyi şey kaçmak

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

işlem bitene kadar bir tmux / screen oturumunda.


2
Orijinal dosyalara bağlantı, kabul edilen cevaplarda olduğu gibi çalışmalıdır.
Chris S,

1
Bu soruya kabul edilmiş bir cevap yok, hangisine atıfta bulunuyorsunuz?
Hamman Samuel,

Bunun >silinmiş dosyaya yeniden yönlendirilmesine ( ) gerek yok mu?
ncasas

1

İlginç soru. Bir görüşmeci, aynı soruyu bana bir iş görüşmesinde de sordu. Ona söylediğim şey, bunu yapmanın kolay bir yolu olmadığı ve genel olarak söz konusu zamana ve emeğe değmediği. Ona bu sorunun çözümünün ne olduğunu düşündüğünü sordum.

  1. Diskte bulunan inode numarasını bulmak için lsof komutunu kullanın, dosya silinmiş olsa bile görünmeye devam eder ... anahtar hala açıktır.
  2. Bir dosya sistemi hata ayıklayıcısı aracılığıyla buna dayanarak bilgileri dosya sisteminden çıkarın.

Verileri / proc / <pid> / fd / N dizininden çekip çıkarabilirim ancak yapmaya çalıştığım şey bu değil.
mbac32768

1

Sleuthkit icat kullanın .

sudo icat /dev/rdisk1s2 5484287 > accidentally_deleted_open_file

Bu, işletim sisteminin dosya sistemi işlevselliğini atlayarak ve doğrudan disk baytlarını ayırarak çalışır.
Flimm

0

Göz korkutucu araçlar olmadan benim için çalışan hızlı çözüm:

1) doğrudan / proc içine bakarak süreci + fd'yi bulun:

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

2) Daha sonra pvatılan , @ nickray ile benzer bir teknik :

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

Bittiğinde Ctrl-C'ye ihtiyacınız olabilir ( ls /proc/{procnum}/fd/{fdnum}dosyanın artık mevcut olmadığını söyleyecektir), ancak tam bayt cinsinden boyutunu biliyorsanız pv -S, sayıma ulaşıldığında çıkmasını sağlamak için kullanabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.