วิธีการกู้คืนไฟล์ที่ถูกลบถ้ามันยังคงเปิดโดยกระบวนการบางอย่าง?


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)

วิธีการกู้คืนนี้important_file?

ฉันลองทำสิ่งที่ชอบ

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

แต่มันไม่ทำอะไรเลย

คำตอบ:


11

หาก / home คือ NFS จะมีไฟล์. nfsNNNNNNNNN ใน / home / vi ที่คุณสามารถเข้าถึง / คัดลอก หาก home เป็นระบบไฟล์ในตัวคุณควรทำสิ่งเดียวกันผ่านลิงก์ / proc / PID / fd / 3:

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

หากคุณต้องการยกเลิกการลบไฟล์จริงนี่คือบล็อกโพสต์ในหัวเรื่อง


1
ตกลงฉันสับสนว่าreadlink /proc/13381/fd/3-> "/ home / vi / important_file (ลบแล้ว)" และ/home/vi/important_file\ \(deleted\)เห็นได้ชัดว่าไม่มีอยู่จริง
วิ

22

... ดีกว่าการคัดลอกในเวลาที่กำหนด (และการรวบรวมเฉพาะเนื้อหาของไฟล์ในเวลานั้น) คือการ " tail -f" ไฟล์นั้นลงในไฟล์ใหม่:

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

(ขอบคุณโปรแกรมเมอร์ที่ระมัดระวังของ tail ที่จะทำงานกับเอาต์พุตไบนารีได้)

ระหว่างรันไทม์tail -fตัวมันเองจะเปิดไฟล์อย่างปลอดภัยป้องกันไม่ให้ถูกลบออกจากดิสก์เมื่อโปรแกรมต้นฉบับสิ้นสุดลง ดังนั้นอย่าหยุดtail -fทันทีหลังจากโปรแกรมต้นฉบับของคุณสิ้นสุด - ตรวจสอบส่วนท้าย/new/path/to/fileก่อนว่าเป็นสิ่งที่คุณต้องการหรือไม่ หากไม่ใช่ (หรือไม่พอใจด้วยเหตุผลอื่นใด) คุณสามารถคัดลอกไฟล์ต้นฉบับอีกครั้ง แต่คราวนี้หลังจากการเขียนทั้งหมดไปยังไฟล์นั้นเสร็จสิ้นโดย "โปรแกรม" และจากtail -f/ proc / PIDoftail / ที่ทำงานอยู่ ไดเรกทอรี fd /


3
สิ่งที่เกี่ยวกับการสร้างฮาร์ดลิงก์ไปยัง / proc / PIDofProgram> / fd / #
becko

2
Invalid cross-device link@becko
Kamil Maciorowski

10

ใช้ lsof เพื่อค้นหาหมายเลข inode และ debugfs เพื่อสร้างฮาร์ดลิงก์ใหม่ ตัวอย่างเช่น:

# 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

ก่อนที่คุณจะบ่นฉันแกล้งบันทึกข้อความด้านบนเนื่องจากฉันไม่มีไฟล์ที่ถูกลบไปตอนนี้ ;-)

ผมใช้miการตั้งค่าเวลาลบและนับเชื่อมโยงไปยังค่าที่เหมาะสม (0 และ 1 ตามลำดับ) แต่มันไม่ทำงานอย่างถูกต้อง - lsคุณสามารถดูซากนับลิงค์ที่ศูนย์ใน ฉันคิดว่าเคอร์เนลอาจแคชข้อมูล inode คุณน่าจะ fsck ในโอกาสแรกหลังจากใช้ debugfs เพื่อให้ปลอดภัย

จากประสบการณ์ของฉันคุณควรสร้างลิงค์โดยใช้ชื่อไฟล์ชั่วคราวแล้วเปลี่ยนชื่อเป็นชื่อที่เหมาะสม การเชื่อมโยงโดยตรงกับชื่อไฟล์ต้นฉบับดูเหมือนว่าจะทำให้ไดเรกทอรีเสียหาย YMMV!


ทำไมคุณแนะนำอย่างนี้ถ้ามันไม่ทำงานอย่างถูกต้องและทำให้ระบบเสียหาย ฉันคิดว่าคุณควรมีข้อจำกัดความรับผิดชอบที่ชัดเจนกว่าในคำตอบว่านี่เป็นเพียง WiP และไม่ควรลองใช้จริงในการผลิต
cnst

3

คุณสามารถเพียงแค่cpไฟล์คือ:

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

แน่นอนหากไฟล์ยังคงถูกแก้ไขคุณจะพบปัญหากับวิธีการนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.