Bagaimana memulihkan file yang dihapus jika masih dibuka oleh beberapa proses?

19
$ cat important_file > /dev/null &
[1] 9711
$ rm important_file 
$ killall -STOP cat

[1]+  Stopped                 cat important_file > /tmp/p
$ ls -l /proc/`pidof cat`/fd/
total 0
lrwx------ 1 vi vi 64 May 13 20:32 0 -> /dev/pts/29
l-wx------ 1 vi vi 64 May 13 20:32 1 -> /tmp/p
lrwx------ 1 vi vi 64 May 13 20:32 2 -> /dev/pts/29
lr-x------ 1 vi vi 64 May 13 20:32 3 -> /home/vi/important_file (deleted)

Bagaimana cara memulihkannya important_file?

Saya mencoba sesuatu seperti

injcode -m dup2 -ofd=3 -ofilename=/tmp/recovered_file -oflags=O_CREAT $PID_OF_CAT

tetapi tidak melakukan apa-apa.

Vi.
sumber

Jawaban:

11

Jika / home adalah NFS, akan ada file .nfsNNNNNNNNNNNN di / home / vi yang dapat Anda akses / salin. Jika home adalah sistem file lokal, Anda harus dapat melakukan hal yang sama melalui tautan / proc / PID / fd / 3:

cp /proc/PID/fd/3 /tmp/recovered_file

Jika Anda ingin membatalkan penghapusan file, berikut adalah posting blog tentang hal itu.

Mark Johnson
sumber
1
OK, saya bingung dengan itu readlink /proc/13381/fd/3-> "/ home / vi / important_file (dihapus)" dan /home/vi/important_file\ \(deleted\)jelas tidak ada.
Vi.
22

... lebih baik daripada menyalin pada waktu tertentu (dan mengumpulkan hanya snapshot waktu dari konten file) adalah dengan " tail -f" file itu menjadi file baru:

tail -c +0 -f /proc/PIDofProgram>/fd/# > /new/path/to/file

(Terima kasih kepada programmer yang berhati-hati, yang bahkan akan bekerja dengan output biner.)

Selama runtime, tail -fitu sendiri membuat file tetap terbuka, dengan aman mencegahnya dibersihkan dari disk ketika program asli berakhir. Dengan demikian, tidak menghentikan tail -fsegera setelah program Anda berakhir asli - memeriksa tail'ed /new/path/to/filepertama apakah itu adalah apa yang Anda inginkan. Jika tidak (atau tidak memuaskan karena alasan lain), Anda dapat menyalin file asli lagi, tetapi kali ini setelah semua penulisan itu selesai dengan "Program" dan dari tail -f'proc / PIDoftail / yang masih berjalan fd / direktori.

Kristen
sumber
3
Bagaimana dengan membuat hardlink ke / proc / PIDofProgram> / fd / #?
becko
2
@becko Invalid cross-device link.
Kamil Maciorowski
10

Gunakan lsof untuk menemukan nomor inode, dan debugfs untuk membuat ulang tautan yang sulit. Sebagai contoh:

# lsof -p 12345 | grep /var/log/messages
syslogd 12345 root    3w   REG                8,3    3000    987654 /var/log/messages (deleted)
# mount | grep var
/dev/sda2 on /var type ext3 (rw)
# debugfs -w /dev/sda2
debugfs: cd log
debugfs: ln <987654> tmp
debugfs: mi tmp
                      Mode    [0100600] 
                   User ID    [0] 
                  Group ID    [0] 
                      Size    [3181271] 
             Creation time    [1375916400] 
         Modification time    [1375916322] 
               Access time    [1375939901]
             Deletion time    [9601027] 0
                Link count    [0] 1
               Block count    [6232] 
                File flags    [0x0] 
...snip...
debugfs:  q
# mv /var/log/tmp /var/log/messages
# ls -al /var/log/messages
-rw------- 0 root root 3301 Aug  8 10:10 /var/log/messages

Sebelum Anda mengeluh, saya memalsukan transkrip di atas karena saya tidak memiliki file yang dihapus saat ini ;-)

Saya gunakan miuntuk mengatur ulang waktu hapus dan jumlah tautan ke nilai yang masuk akal (masing-masing 0 dan 1), tetapi tidak berfungsi dengan baik - Anda dapat melihat jumlah tautan tetap nol di ls. Saya pikir kernel mungkin menyimpan data inode. Anda mungkin harus fsck pada kesempatan paling awal setelah menggunakan debugfs, untuk berada di sisi yang aman.

Dalam pengalaman saya, Anda harus membuat tautan menggunakan nama file sementara dan kemudian mengganti nama menjadi nama yang tepat. Menautkannya langsung ke nama file asli tampaknya menyebabkan korupsi direktori. YMMV!

Andrew Gallagher
sumber
Mengapa Anda menyarankan ini jika tidak benar-benar berfungsi dan menyebabkan kerusakan sistem? Saya pikir Anda harus memiliki disclaimer yang lebih jelas dalam jawaban bahwa ini hanyalah WiP, dan seharusnya tidak benar-benar diadili dalam produksi.
cnst
3

Anda bisa langsung cpfile, yaitu:

cp /proc/<pid>/fd/<fdno> /new/path/to/file

Tentu saja, jika file tersebut masih sedang dimodifikasi, Anda akan mengalami masalah dengan pendekatan ini.

ninjalj
sumber