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


10

สมมติว่าไฟล์บันทึก apache ถูกลบ แต่ถูกระงับโดย apache นี่คือสิ่งที่ฉันทำ:

pid=$(lsof | grep text.txt | awk '/deleted/ {print $2}')
fd=$(lsof | grep text.txt | awk '/deleted/ {print $4}' | grep -oE "[[:digit:]]{1,}")

cp /proc/$pid/fd/$fd directorytobecopied/testfile.txt

นี่คือสิ่งที่ฉันกำลังทำเพื่อกู้คืนไฟล์และนำกลับไปวางไว้ที่เดิม มีวิธีที่ง่ายกว่าในการทำเช่นนี้เพราะรหัสด้านบนดูไม่ดี นอกจากนี้ฉันจะรู้ได้อย่างไรว่าไฟล์ถูกลบไปที่ไหน ( directorytobececied ) เพื่อที่ฉันจะได้ไม่ต้องถามใครสักคนว่าไฟล์นั้นอยู่ที่ใดและอยู่ที่นั่น


lsof / | awk '(/deleted/||/abc.txt/) {print "FD :-",$4,"| File Name:-",$9}'
ราหุลปาติล

คำตอบ:


14

หากไฟล์ถูกลบ แต่ยังคงเปิดอยู่นั่นหมายความว่าไฟล์นั้นยังคงมีอยู่ในระบบไฟล์ (มีinode ) แต่มีจำนวนฮาร์ดลิงก์เป็น 0 เนื่องจากไม่มีลิงก์ไปยังไฟล์คุณจะไม่สามารถเปิดด้วยชื่อ . ไม่มีสิ่งอำนวยความสะดวกในการเปิดไฟล์โดย inode เช่นกัน

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

ลินุกซ์ exposes /procเปิดไฟล์ผ่านการเชื่อมโยงสัญลักษณ์พิเศษภายใต้ ลิงก์เหล่านี้ถูกเรียก/proc/12345/fd/42โดยที่ 12345 เป็น PID ของกระบวนการและ 42 คือหมายเลขของไฟล์ descriptorในกระบวนการนั้น โปรแกรมที่รันด้วยผู้ใช้เดียวกันกับกระบวนการนั้นสามารถเข้าถึงไฟล์ได้ (สิทธิ์ในการอ่าน / เขียน / ดำเนินการเหมือนกันกับที่คุณมีเมื่อไฟล์ถูกลบ)

ชื่อตามที่ไฟล์นั้นถูกเปิดก็ยังคงปรากฏอยู่ในเป้าหมายของการเชื่อมโยงสัญลักษณ์: ถ้าไฟล์นั้นแล้วเป้าหมายของการเชื่อมโยงคือ/var/log/apache/foo.log /var/log/apache/foo.log (deleted)(หากไฟล์ถูกเปลี่ยนชื่อหลังจากเปิดแล้วเป้าหมายของ symlink อาจแสดงถึงการเปลี่ยนชื่อ)

ดังนั้นคุณสามารถกู้คืนเนื้อหาของไฟล์ที่ถูกลบที่เปิดอยู่เนื่องจาก PID ของกระบวนการที่เปิดอยู่และตัวบ่งชี้ที่เปิดในลักษณะนี้:

recover_open_deleted_file () {
  old_name=$(readlink "$1")
  case "$old_name" in
    *' (deleted)')
      old_name=${old_name%' (deleted)'}
      if [ -e "$old_name" ]; then
        new_name=$(TMPDIR=${old_name%/*} mktemp)
        echo "$oldname has been replaced, recovering content to $new_name"
      else
        new_name="$old_name"
      fi
      cat <"$1" >"$new_name";;
    *) echo "File is not deleted, doing nothing";;
  esac
}
recover_open_deleted_file "/proc/$pid/fd/$fd"

หากคุณรู้ ID กระบวนการ แต่ไม่ใช่ตัวบ่งชี้คุณสามารถกู้คืนไฟล์ทั้งหมดได้

for x in /proc/$pid/fd/*; do
  recover_open_deleted_file "$x"
done

หากคุณไม่ทราบ ID กระบวนการคุณสามารถค้นหาระหว่างกระบวนการทั้งหมดได้:

for x in /proc/[1-9]*/fd/*; do
  case $(readlink "$x") in
    /var/log/apache/*) recover_open_deleted_file "$x";;
  esac
done

นอกจากนี้คุณยังสามารถรับรายการนี้โดยแยกวิเคราะห์ผลลัพธ์lsofแต่มันก็ไม่ง่ายกว่าหรือน่าเชื่อถือกว่าและพกพาได้มากกว่า


คุณสามารถเปิด / proc / x / fd / y สำหรับการอ่านหรือการเขียนโดยไม่คำนึงว่า x ได้เปิดไว้สำหรับการอ่านหรือเขียนหรือไม่
Stéphane Chazelas

เหตุใดระบบปฏิบัติการ unix จึงอนุญาตให้ลบไฟล์เมื่อเปิด ... ในขณะที่เราไม่สามารถทำได้ใน windows มีคำอธิบายใด ๆ
munish

@munish Windows เริ่มต้นจากรูปแบบมัลติทาสกิ้งแบบมีส่วนร่วม: หากแอปพลิเคชันทำงานผิดปกติก็อาจทำให้ระบบล่มได้ ปัญหาส่วนใหญ่ได้รับการแก้ไขแล้วในขณะนี้ แต่ Windows ยังคงอนุญาตให้แอปพลิเคชันขโมยไฟล์: ตราบใดที่ไฟล์เปิดอยู่จะไม่สามารถเปลี่ยนชื่อหรือลบได้ Unix ไม่อนุญาตสิ่งนี้: การลบหรือเปลี่ยนชื่อไฟล์เป็น orthogonal ไม่ให้เปิด
Gilles 'หยุดความชั่วร้าย'

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