วิธีกู้คืนไฟล์ที่ถูกลบด้วยคำสั่ง rm -rf บน Linux
หากคุณเผลอใช้คำสั่ง rm -rf ลบข้อมูลสำคัญ ให้หยุดการเขียนข้อมูลลงดิสก์ทันที บทความนี้แนะนำขั้นตอนการกู้คืนไฟล์บนระบบไฟล์ ext4 อย่างถูกต้อง เพื่อป้องกันไม่ให้ข้อมูลถูกเขียนทับ
สิ่งที่ต้องทำภายใน 60 วินาทีแรก
ปัจจัยสองประการเป็นตัวตัดสินว่าคุณจะกู้คืนไฟล์ที่ถูกลบด้วย rm -rf ได้หรือไม่ และทั้งสองประการนี้ต้องทำก่อนที่คุณจะเปิดโปรแกรมค้นหา ให้หยุดการเขียนข้อมูลลงในระบบไฟล์นั้นทันที จากนั้นให้นำระบบไฟล์ออกจากสถานะการใช้งาน โดยการ unmount หรือ remount เป็นแบบ read-only
rm ไม่ได้ลบข้อมูลใดๆ ออกไปจริง มันเพียงแค่ลบรายการในไดเรกทอรี แล้วทำเครื่องหมายที่ inode และบล็อกข้อมูลของไฟล์นั้นว่าว่างเปล่า ไบต์ข้อมูลยังคงอยู่บนอุปกรณ์ และจะอยู่ที่นั่นจนกว่าตัวจัดสรรบล็อก (block allocator) จะส่งมอบบล็อกเหล่านั้นให้กับกระบวนการอื่น และกระบวนการนั้นเขียนทับข้อมูลเดิม ทุกวินาทีที่ระบบไฟล์ยังคงถูก mount และใช้งานอยู่ daemon อาจเขียนบรรทัด log หรือฐานข้อมูลอาจ flush หน้าข้อมูลลงดิสก์ ซึ่งการเขียนข้อมูลเหล่านี้อาจไปทับบล็อกที่คุณต้องการกู้คืนได้
ดังนั้น คำสั่งแรกที่ต้องใช้คือคำสั่งที่หยุดการเขียนข้อมูล ไม่ใช่คำสั่งที่ใช้กู้คืนไฟล์
sudo systemctl stop nginx postgresql
sudo umount /mnt/dataหาก umount ตอบกลับด้วย umount: /mnt/data: target is busy. ให้ตรวจสอบว่ากระบวนการใดที่กำลังใช้งานระบบไฟล์นั้นอยู่
sudo fuser -vm /mnt/data
sudo lsof +D /mnt/dataหากคุณไม่สามารถปลดการใช้งานได้ ให้ remount เป็นแบบ read-only แทน การ mount แบบ read-only จะหยุดการจัดสรรพื้นที่ใหม่ ซึ่งเป็นสิ่งที่คุณต้องการเป็นส่วนใหญ่
sudo mount -o remount,ro /mnt/dataหากเส้นทางที่ไฟล์ถูกลบอยู่บนระบบไฟล์ root การดำเนินการจะยากขึ้น sudo mount -o remount,ro / มักจะล้มเหลวด้วย mount: /: cannot remount /dev/vda1 read-only. เนื่องจากกระบวนการที่ทำงานอยู่มีการเปิดไฟล์ค้างไว้เพื่อเขียน และ kernel จะไม่บังคับปิดกระบวนการเหล่านั้น สำหรับ VPS วิธีปฏิบัติที่ใช้ได้จริงคือการใช้โหมด rescue หรือ recovery ของผู้ให้บริการ ซึ่งจะบูตระบบ live แยกต่างหากโดยที่ดิสก์ของคุณถูกเชื่อมต่ออยู่แต่ไม่ได้ถูก mount คำสั่งทั้งหมดด้านล่างนี้จะทำงานกับอุปกรณ์ที่ไม่มีการเขียนข้อมูลใดๆ ลงไป
กฎข้อหนึ่งที่ใช้กับคู่มือฉบับนี้ทั้งหมดคือ ห้ามเขียนไฟล์ที่กู้คืนได้, ไฟล์ disk image หรือเครื่องมือที่ติดตั้งใหม่ลงบนระบบไฟล์ที่คุณกำลังกู้คืนข้อมูล ให้เชื่อมต่อ volume ที่สอง หรือส่งผลลัพธ์ไปยังเครื่องอื่นผ่าน SSH แทน
เหตุใดการกู้คืนข้อมูลหลังใช้ rm -rf บน ext4 จึงแทบเป็นไปไม่ได้
กำหนดความคาดหวังของคุณก่อนที่จะติดตั้งซอฟต์แวร์ใดๆ ตรวจสอบให้แน่ใจว่าคุณกำลังใช้งานระบบไฟล์ประเภทใด:
lsblk -fบน ext4 ซึ่งเป็นค่าเริ่มต้นของ VPS เกือบทุกแห่ง ตำแหน่งข้อมูลของไฟล์จะถูกเก็บไว้ใน inode ในรูปแบบ extent tree โดย extent คือบันทึกที่ระบุว่า logical block ลำดับที่ N ของไฟล์นั้น เริ่มต้นที่ physical block ลำดับที่ M และมีความยาว L บล็อก สำหรับไฟล์ขนาดเล็ก ข้อมูล extent สูงสุด 4 รายการจะถูกเก็บไว้ภายใน inode โดยตรง ส่วนไฟล์ขนาดใหญ่จะชี้ไปยังบล็อกเพิ่มเติมที่เก็บส่วนที่เหลือของ tree เอาไว้
เมื่อลิงก์สุดท้ายของไฟล์ถูกลบออก ext4 จะไล่ตาม tree นั้น ส่งคืน extent ทั้งหมดกลับไปยังตัวจัดสรรบล็อก (block allocator) และล้างข้อมูล tree ออกจาก inode จากนั้น inode จะถูกทำเครื่องหมายว่าว่างและประทับเวลาการลบไว้ แต่ตัวข้อมูลจริงจะยังคงอยู่ครบถ้วน เพียงแต่บันทึกที่ระบุว่าข้อมูลเหล่านั้นเคยอยู่ที่ใดได้ถูกลบไปแล้ว
นี่คือจุดที่แตกต่างจาก ext3 ซึ่ง inode ที่ถูกลบจะยังคงเก็บข้อมูลเพียงพอให้เครื่องมืออย่าง ext3grep ติดตามได้ คุณยังสามารถแสดงรายการ inode ที่ถูกลบไปแล้วบน ext4 ได้ด้วยคำสั่ง:
sudo debugfs -R lsdel /dev/vdb1debugfs จะเปิดอุปกรณ์ในโหมดอ่านอย่างเดียว (read-only) เว้นแต่คุณจะระบุ -w ดังนั้นการใช้งานบนอุปกรณ์ที่ไม่ได้ mount จึงปลอดภัยและไม่มีความเสี่ยงใดๆ ในการลองทำ inode จะถูกแสดงรายการออกมา แต่การดัมพ์ข้อมูล (dump) จะไปสิ้นสุดเพียงแค่นั้น เพราะ block map ที่ inode เคยเก็บไว้ถูกล้างไปแล้ว ทำให้ dump ไม่มีข้อมูลให้ติดตามต่อ
มีเครื่องมือสองตัวที่พยายามแก้ปัญหานี้ด้วยการอ่านจาก journal โดย journal คือวงแหวนขนาดคงที่ที่ ext4 ใช้เพื่อรักษาความสอดคล้องของ metadata ในกรณีที่ระบบขัดข้อง ซึ่งอาจยังคงเก็บสำเนา inode รุ่นเก่าก่อนการลบไว้ได้ extundelete และ ext4magic จะทำการค้นหาในส่วนนี้ ตรวจสอบขนาดของ journal ที่คุณใช้งานอยู่:
sudo dumpe2fs -h /dev/vdb1 | grep -i journaljournal เก็บเฉพาะ metadata และมีขนาดเล็ก ดังนั้นกิจกรรมการเขียนข้อมูลทั่วไปจะวนทับข้อมูลในส่วนนี้อย่างรวดเร็ว บนเซิร์ฟเวอร์ที่กำลังทำงานอยู่ ช่วงเวลาที่ inode ก่อนการลบจะยังคงหลงเหลืออยู่มีเพียงไม่กี่นาทีเท่านั้น เครื่องมือทั้งสองตัวไม่มีการดูแลรักษาอย่างต่อเนื่องและไม่ได้ถูกบรรจุอยู่ในทุก distribution ให้ถือว่าทั้งสองตัวเป็นเพียงความหวังริบหรี่เท่านั้น ควรเรียกใช้งานกับอุปกรณ์ที่ไม่ได้ mount หรือไฟล์ disk image และอย่าแปลกใจหากเครื่องมือไม่พบข้อมูลใดๆ
หาก lsblk -f รายงานผลเป็น xfs สถานการณ์ก็ไม่ดีขึ้น เนื่องจากไม่มีวิธีการกู้คืนไฟล์ที่รองรับสำหรับ XFS เช่นกัน ลำดับของตัวเลือกด้านล่างนี้จึงไม่มีผลเปลี่ยนแปลงใดๆ
ไฟล์ยังคงถูกเปิดใช้งานอยู่ใน process ที่กำลังทำงานอยู่หรือไม่?
นี่เป็นวิธีเดียวในการกู้คืนข้อมูลบนหน้านี้ที่มีโอกาสสำเร็จสูง และเป็นเหตุผลว่าทำไมคุณไม่ควร restart service ที่กำลังใช้งานไฟล์นั้นอยู่
ไฟล์จะถูกลบออกอย่างแท้จริงก็ต่อเมื่อตัวนับสองค่าลดลงเหลือศูนย์ ได้แก่ จำนวนรายการใน directory ที่ชี้ไปยัง inode นั้น และจำนวน file descriptor ที่เปิดอยู่ rm จะลดค่าตัวนับแรกให้เหลือศูนย์ หากยังมี process ใดที่เปิดไฟล์นั้นค้างไว้ ตัวนับที่สองจะไม่เป็นศูนย์ ดังนั้น inode และบล็อกข้อมูลของมันจะยังคงถูกจัดสรรไว้และข้อมูลยังคงสามารถอ่านได้
ค้นหาไฟล์ที่เปิดอยู่ซึ่งมีจำนวน link ลดลงเหลือศูนย์:
sudo lsof +L1+L1 หมายถึงการแสดงรายการไฟล์ที่เปิดอยู่ซึ่งมีจำนวน link ต่ำกว่า 1 ผลลัพธ์แต่ละรายการจะแสดง process, หมายเลข file descriptor, NLINK ของ 0 และ path ที่ลงท้ายด้วย (deleted) ให้นำ PID และหมายเลข descriptor ไปที่ /proc:
sudo ls -l /proc/1234/fdรายการที่ปรากฏจะมีลักษณะเป็น 3 -> /var/log/app/events.log (deleted) ลิงก์นั้นยังคงเข้าถึงข้อมูลได้ ให้คัดลอกข้อมูลออกมายัง filesystem อื่น:
sudo cp /proc/1234/fd/3 /mnt/rescue/events.logให้ใช้ cp ไม่ใช่ mv การเปิด /proc/1234/fd/3 จะทำให้คุณได้ handle ใหม่ที่ชี้ไปยัง inode เดียวกันโดยเริ่มจาก offset ที่ศูนย์ คุณจึงได้ไฟล์ทั้งหมดแทนที่จะได้เฉพาะส่วนที่อยู่ถัดจากตำแหน่งปัจจุบันของผู้เขียน
มีข้อจำกัดสองประการที่ควรทราบ: โครงสร้าง directory ที่ถูกลบไปแล้วไม่สามารถกู้คืนด้วยวิธีนี้ได้ เนื่องจากมีเพียงไฟล์แต่ละไฟล์ที่ process เปิดค้างไว้เท่านั้นที่ยังคงอยู่ และไฟล์ฐานข้อมูลที่ถูกคัดลอกในขณะที่ engine กำลังเขียนข้อมูลอยู่จะเป็นสำเนาแบบ crash-consistent ดังนั้นควรวางแผนที่จะใช้เครื่องมือ recovery ของตัว engine เองแทนที่จะถือว่าไฟล์นั้นสมบูรณ์ รายการที่ lsof แสดงโดยมี mem แทนที่หมายเลข descriptor คือไฟล์ที่ถูก memory mapped ซึ่งจะไม่มีรายการ /proc/<pid>/fd ให้คัดลอกออกมาได้
คุณมี snapshot บน btrfs, ZFS หรือ LVM หรือไม่?
หากระบบไฟล์รองรับการทำ snapshot ไฟล์ที่ถูกลบไปแล้วจะยังคงอยู่ใน snapshot นั้นโดยไม่มีการเปลี่ยนแปลง วิธีนี้จะช่วยได้ก็ต่อเมื่อมีการสร้าง snapshot ไว้ก่อนที่จะเกิดการลบเท่านั้น สิ่งที่คุณสร้างขึ้นในตอนนี้ไม่สามารถย้อนกลับไปแก้ไขอดีตได้
btrfs เก็บ snapshot ไว้ในรูปแบบ subvolume:
sudo btrfs subvolume list /ให้เรียกดู snapshot และคัดลอก path ที่ต้องการออกมาด้วย cp -a แนะนำให้ใช้วิธีคัดลอกเฉพาะไฟล์ที่จำเป็นแทนการย้อนกลับ (rollback) ทั้ง subvolume เพราะการทำ rollback จะทำให้ข้อมูลทั้งหมดที่เขียนลงไปหลังจากช่วงเวลาที่ทำ snapshot นั้นสูญหายไปด้วย
ZFS จะแสดง snapshot ทุกตัวเป็นไดเรกทอรีแบบอ่านได้อย่างเดียว (read-only):
zfs list -t snapshot
ls /tank/data/.zfs/snapshot/ไดเรกทอรี .zfs เป็นไดเรกทอรีที่ถูกซ่อนไว้และจะไม่ปรากฏเมื่อใช้คำสั่ง ls ในระดับ root ของ dataset แต่คุณสามารถเข้าถึงได้โดยการระบุชื่อไดเรกทอรีโดยตรง ให้คัดลอกไฟล์ออกมาจากที่นั่น ส่วนคำสั่ง zfs rollback จะเป็นการย้อน dataset ทั้งหมดกลับไปและทำลาย snapshot ทุกตัวที่ใหม่กว่า snapshot ที่คุณระบุ ดังนั้นให้ใช้เป็นทางเลือกสุดท้ายเท่านั้น
LVM snapshot คือ volume แบบ copy-on-write ที่มีขนาดคงที่:
sudo lvs
sudo mount -o ro /dev/vg0/data-snap /mnt/snapให้ mount snapshot แบบอ่านได้อย่างเดียว (read-only) แล้วคัดลอกไฟล์ออกมา ตรวจสอบสถานะด้วย lvs ก่อนที่จะใช้งาน เพราะหาก LVM snapshot มีข้อมูลเต็มพื้นที่ที่จัดสรรไว้ เคอร์เนลจะทำให้ snapshot นั้นใช้งานไม่ได้ และเมื่อถึงจุดนั้นเนื้อหาภายในก็จะสูญหายไปทั้งหมด
snapshot ไม่ใช่การสำรองข้อมูล (backup) เนื่องจากมันถูกเก็บไว้บนดิสก์หรือ pool เดียวกันกับข้อมูลต้นฉบับ จึงมีความเสี่ยงต่อความเสียหายในรูปแบบเดียวกับข้อมูลต้นฉบับ อย่างไรก็ตาม snapshot มีประโยชน์มากในการแก้ไขข้อผิดพลาดที่เพิ่งเกิดขึ้นเมื่อไม่กี่นาทีก่อน ซึ่งเป็นจุดประสงค์หลักของกรณีนี้
การกู้คืนข้อมูลด้วย PhotoRec โดยใช้ไฟล์อิมเมจแทนการอ่านจากดิสก์โดยตรง
หากวิธีข้างต้นไม่ได้ผล สิ่งสุดท้ายที่เหลืออยู่คือการทำ carving ซึ่งเป็นการสแกนอุปกรณ์แบบ raw เพื่อหาแพทเทิร์นของไบต์ที่ระบุจุดเริ่มต้นของประเภทไฟล์ที่รู้จัก แล้วจึงเขียนข้อมูลที่ตามมาออกมา การทำ carving จะอ่านเฉพาะข้อมูลไฟล์เท่านั้น ส่วนชื่อไฟล์ โครงสร้างไดเรกทอรี การประทับเวลา และความเป็นเจ้าของไฟล์ถือเป็น metadata ของระบบไฟล์ ซึ่ง metadata เหล่านี้ถูก rm ทำลายไปแล้ว จึงไม่สามารถกู้คืนกลับมาได้ คุณจะได้ไฟล์ที่ชื่อว่า f0384512.jpg อยู่ในไดเรกทอรีผลลัพธ์ที่มีการระบุหมายเลขไว้ และคุณต้องคัดแยกไฟล์เหล่านั้นด้วยตนเอง
มีกฎสองข้อที่กำหนดว่าวิธีนี้จะได้ผลหรือไม่
ข้อแรก ให้สร้างอิมเมจของอุปกรณ์ก่อนที่จะใช้เครื่องมือใดๆ กับมัน บน Debian และ Ubuntu แพ็กเกจที่ใช้คือ gddrescue และไบนารีที่ติดตั้งคือ ddrescue
sudo apt update && sudo apt install -y gddrescue testdisk
sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map/mnt/rescue ต้องอยู่ในอุปกรณ์อื่นที่มีพื้นที่ว่างอย่างน้อยเท่ากับขนาดของพาร์ทิชันนั้น lsblk -b จะแสดงขนาดที่แน่นอนเป็นไบต์ ไฟล์แผนผัง (map file) ช่วยให้การคัดลอกที่ถูกขัดจังหวะสามารถดำเนินการต่อได้โดยไม่ต้องเริ่มใหม่ทั้งหมด เมื่อคุณได้ไฟล์อิมเมจแล้ว คุณสามารถลองใช้เครื่องมือตัวที่สองกับข้อมูลชุดเดิมได้ในภายหลัง ซึ่งคุณไม่สามารถทำได้หากเครื่องมือตัวแรกเขียนทับลงบนดิสก์ไปแล้ว
ข้อสอง ให้ชี้เครื่องมือการกู้คืนไปที่ไฟล์อิมเมจ
sudo photorec /d /mnt/rescue/recup /mnt/rescue/vdb1.imgphotorec จะเปิดเมนูข้อความขึ้นมา ให้เลือกพาร์ทิชัน เลือกประเภทระบบไฟล์ เลือกประเภทลายเซ็นไฟล์ (file signatures) ที่ต้องการค้นหา แล้วจึงเลือกไดเรกทอรีปลายทาง ให้จำกัดรายการลายเซ็นเฉพาะประเภทไฟล์ที่คุณทำหายจริงๆ ก่อนเริ่มทำงาน เพราะรายการเริ่มต้นจะค้นหาทุกอย่างและทำให้คุณได้ไฟล์ชิ้นส่วนต่างๆ ออกมานับหมื่นไฟล์ซึ่งต้องมาคัดแยกอีกที
testdisk ซึ่งมาจากแพ็กเกจเดียวกัน มีฟังก์ชันกู้คืนไฟล์ที่ถูกลบของตัวเอง แต่รองรับเฉพาะ FAT, exFAT, NTFS และ ext2 เท่านั้น สำหรับ ext4 คุณต้องใช้ photorec
ให้คาดการณ์ไว้ว่าไฟล์ที่กระจัดกระจาย (fragmented) จะถูกกู้คืนมาในสภาพที่เสียหาย การทำ carving สมมติว่าบล็อกของไฟล์นั้นเรียงต่อกัน ดังนั้นไฟล์ที่ตัวจัดสรรข้อมูล (allocator) แยกส่วนไว้บนดิสก์จะถูกประกอบกลับมาผิดพลาดหรือไม่ก็หาไม่พบเลย ไฟล์สื่อ (media files) มักจะกู้คืนได้ค่อนข้างดีเพราะมีส่วนหัว (header) ที่ชัดเจน ส่วนไฟล์ข้อความธรรมดา ไฟล์คอนฟิกูเรชัน และซอร์สโค้ดมักจะกู้คืนได้ยาก เพราะไม่มีลายเซ็นไบต์ที่ระบุจุดเริ่มต้นของสคริปต์ shell ได้อย่างชัดเจน
ช่องว่างที่เกินมา: สาเหตุที่ path ผิดถูกลบ
อุบัติเหตุส่วนใหญ่ที่เกิดกับ rm -rf เป็นปัญหาของ shell โดย rm จะได้รับรายการของ path และลบทีละรายการตามลำดับ มันไม่ทราบถึงเจตนาของคุณ
กรณีคลาสสิกคือการมีช่องว่างเพียงช่องเดียว:
rm -rf /home/deploy/app /old
rm -rf /home/deploy/app/oldบรรทัดแรกประกอบด้วยอาร์กิวเมนต์สองตัว มันจะลบแอปพลิเคชันทิ้ง จากนั้นจึงลบ /old หาก /old ไม่มีอยู่จริง rm จะไม่แสดงผลลัพธ์ใดๆ ออกมาเลย เพราะ -f จะระงับข้อความแจ้งเตือนกรณีไม่พบไฟล์ ความเงียบไม่ใช่การยืนยันว่าสำเร็จ
รูปแบบที่สองคือตัวแปรที่ไม่ได้ใส่เครื่องหมายคำพูดและมีช่องว่างอยู่ภายใน:
dir="/srv/my app"
rm -rf $dirShell จะแยกค่าตามช่องว่าง ส่งผลให้ rm ได้รับ /srv/my และ app เป็น path แยกกันสองรายการ หากเขียนเป็น rm -rf "$dir" จะถือเป็น path เดียว
รูปแบบที่สามคือตัวแปรว่าง ซึ่งมักเกิดจากคำสั่งที่ควรจะเติมค่าลงไปนั้นทำงานล้มเหลว:
rm -rf "$TARGET"/*เมื่อ TARGET ไม่ถูกกำหนดค่า มันจะขยายผลกลายเป็น rm -rf /* ซึ่ง GNU rm จะปฏิเสธการทำงานในรูปแบบเปล่าๆ โดย rm -rf / จะแสดง rm: it is dangerous to operate recursively on '/' แล้วหยุดทำงาน แต่สำหรับรูปแบบ glob จะไม่มีการป้องกันเช่นนี้ เพราะ shell จะแทนที่ /* ด้วยรายการ path จริงในระดับบนสุดก่อนที่ rm จะเริ่มทำงาน และเนื่องจาก / ไม่ใช่หนึ่งในนั้น ตัวป้องกันจึงไม่ทำงาน
นิสัยที่ช่วยป้องกันความผิดพลาดครั้งต่อไป
- ใส่เครื่องหมายคำพูดครอบตัวแปรทุกตัวที่ใช้เป็น path เสมอ เขียน
"$dir"ทุกครั้ง รวมถึงภายในคำสั่งทดสอบและลูป - หยุดทำงานหากตัวแปรว่างเปล่า
rm -rf "${TARGET:?TARGET is not set}"/*จะทำให้ shell หยุดทำงานพร้อมแสดงข้อความของคุณก่อนที่rmจะเริ่มทำงาน ในกรณีที่TARGETไม่ได้ถูกกำหนดค่าหรือเป็นค่าว่าง ให้ใส่set -euo pipefailไว้ที่ส่วนบนสุดของสคริปต์ที่มีการลบไฟล์ - เพิ่ม
--one-file-systemคำสั่งนี้จะบอกให้rmข้ามไดเรกทอรีที่อยู่บนระบบไฟล์อื่นที่ไม่ใช่ระบบไฟล์เดียวกับอาร์กิวเมนต์ที่คุณระบุ เพื่อป้องกันไม่ให้การลบแบบ recursive เข้าไปลบไฟล์ใน volume สำรองที่ mount ไว้หรือ bind mount - อย่าลบไฟล์ในฐานะ root บัญชีผู้ใช้ของบริการควรมีสิทธิ์ทำลายได้เฉพาะสิ่งที่ตนเองเป็นเจ้าของเท่านั้น ซึ่งเป็นเหตุผลสำคัญของการ รันแต่ละบริการด้วยผู้ใช้ที่ไม่มีสิทธิ์พิเศษ หากคุณไม่แน่ใจว่าบัญชีที่กำหนดสามารถเข้าถึงอะไรได้บ้าง การ อ่านค่า permission bits ในรายการ ls จะให้คำตอบได้ด้วยคำสั่งเดียว
- แสดงรายการไฟล์ก่อนที่จะดำเนินการจริง ในสคริปต์ ให้สร้าง path ขึ้นมาก่อน จากนั้น
printf '%s\n'รายการเหล่านั้นออกมา ตรวจสอบผลลัพธ์ แล้วจึงค่อยทำการลบในรอบที่สอง - เก็บคำสั่งสำหรับจัดการถังขยะไว้ใกล้ตัว
sudo apt install trash-cliมอบเครื่องมืออย่างtrash-put,trash-list,trash-restoreและtrash-emptyให้คุณ ไฟล์ที่ถูกลบจะย้ายไปที่~/.local/share/Trashและtrash-empty 30จะล้างข้อมูลที่เก่าเกินสามสิบวันออกให้
การทำ alias rm ให้เป็น trash-put ฟังดูเป็นขั้นตอนถัดไปที่สมเหตุสมผล แต่นั่นคือกับดัก การทำ alias จะสร้างความเคยชินที่ทำให้คุณพลาดเมื่อไปใช้เซิร์ฟเวอร์เครื่องอื่นที่ไม่ได้ตั้งค่านี้ไว้ และ alias ไม่มีผลภายในสคริปต์ซึ่งเป็นจุดที่มักเกิดความผิดพลาดราคาแพง ให้พิมพ์ trash-put ด้วยความตั้งใจแทนจะดีกว่า
การกู้คืนเพียงวิธีเดียวที่ได้ผลเสมอ
ทุกสิ่งที่กล่าวมาข้างต้นเป็นเพียงโอกาส แต่การสำรองข้อมูลไม่ใช่เรื่องของโอกาส
สิ่งสำคัญสองประการที่ทำให้การสำรองข้อมูลเป็นจริงคือ การทำงานตามกำหนดเวลาโดยที่คุณไม่ต้องคอยจำ และการที่คุณเคยทดสอบกู้คืนข้อมูลจากแหล่งนั้นอย่างน้อยหนึ่งครั้ง แหล่งเก็บข้อมูลที่คุณไม่เคยทดสอบกู้คืนมาก่อนเป็นเพียงความเชื่อเท่านั้น เพราะปัจจัยที่ทำให้การสำรองข้อมูลใช้งานไม่ได้ (เช่น การระบุ path ผิดในรายการที่ต้องการสำรอง หรือรหัสผ่านของ repository ที่ไม่มีใครจดไว้) จะปรากฏให้เห็นก็ต่อเมื่อถึงวันที่คุณจำเป็นต้องใช้งานจริงเท่านั้น
สำหรับ restic การกู้คืนข้อมูลทำได้ด้วยคำสั่งสองชุด
restic -r /srv/restic-repo snapshots
restic -r /srv/restic-repo restore latest --target /mnt/rescue --include /srv/appdataควรเลือกกู้คืนลงในไดเรกทอรีว่างแทนการเขียนทับ path จริง เพื่อให้คุณสามารถเปรียบเทียบข้อมูลทั้งสองชุดก่อนที่จะย้ายไฟล์ไปแทนที่ การตั้งค่าการสำรองข้อมูลด้วย restic บน VPS ครอบคลุมถึงการตั้งค่า repository และ systemd timer ที่ใช้รันงานดังกล่าว
สำหรับ Borg:
borg list /srv/borg-repo
borg extract /srv/borg-repo::daily-2026-08-08 srv/appdatapath ภายใน archive ของ Borg จะถูกจัดเก็บโดยไม่มีเครื่องหมาย slash นำหน้า ดังนั้น srv/appdata จึงตรงกัน แต่ /srv/appdata จะไม่พบข้อมูลใดๆ borg extract จะเขียนข้อมูลลงในไดเรกทอรีที่กำลังทำงานอยู่ ดังนั้นควรใช้ cd ไปยังไดเรกทอรีชั่วคราวก่อน
หากคุณยังไม่ได้ตัดสินใจเลือกเครื่องมือ การเปรียบเทียบระหว่าง restic และ Borg จะช่วยอธิบายเรื่องการทำ deduplication และ repository แบบ append-only ซึ่งเป็นคุณสมบัติที่ป้องกันไม่ให้เซิร์ฟเวอร์ที่ถูกบุกรุกสามารถลบประวัติการสำรองข้อมูลของตนเองได้ คุณสามารถเลือกใช้เครื่องมือใดก็ได้ สิ่งที่ผิดพลาดที่สุดคือการไม่เลือกใช้เครื่องมือใดเลย
เซิร์ฟเวอร์เครื่องใหม่เป็นช่วงเวลาที่คุ้มค่าที่สุดในการตั้งค่านี้ ก่อนที่จะมีข้อมูลใดๆ ที่สำคัญพอจะสูญหายไป สิบนาทีแรกบน VPS เครื่องใหม่ คือช่วงเวลาที่ควรดำเนินการเรื่องนี้ ควบคู่ไปกับการตั้งค่า SSH และ firewall
จากนั้นให้บันทึกรายการแจ้งเตือนในปฏิทินของคุณ: กู้คืนไดเรกทอรีหนึ่งรายการจาก repository ไปยัง /tmp ทุกเดือนและตรวจสอบไฟล์เหล่านั้น นิสัยเพียงอย่างเดียวนี้มีค่ามากกว่าเครื่องมือทุกตัวในหน้านี้รวมกัน
FAQ
ฉันสามารถกู้คืนไฟล์ที่ถูกลบใน ext4 ได้หรือไม่?
โดยปกติแล้วไม่ได้ เมื่อลิงก์สุดท้ายของไฟล์ถูกลบออก ext4 จะล้าง extent tree ออกจาก inode ทำให้ไม่มีข้อมูลบนดิสก์บันทึกตำแหน่งที่ข้อมูลเคยอยู่ extundelete และ ext4magic จะค้นหาใน ext4 journal เพื่อหา inode ฉบับก่อนหน้า ซึ่งจะช่วยได้ก็ต่อเมื่อการลบเพิ่งเกิดขึ้นเมื่อไม่กี่นาทีก่อนและระบบไฟล์ไม่ได้มีการเขียนข้อมูลใหม่หลังจากนั้น ทั้งสองโครงการไม่มีการดูแลรักษาอย่างต่อเนื่องแล้ว ให้รันเครื่องมือเหล่านี้กับอุปกรณ์ที่ไม่ได้ mount หรือไฟล์อิมเมจของดิสก์เท่านั้น ห้ามรันบนระบบไฟล์ที่กำลัง mount อยู่ และตรวจสอบอุปกรณ์ที่คุณกำลังทำงานด้วยก่อนโดยใช้ sudo dumpe2fs -h /dev/vdb1 | grep -i journal
บริการหนึ่งยังเปิดไฟล์ที่ถูกลบอยู่ ฉันจะกู้คืนมันได้ไหม?
ได้ และนี่คือกรณีที่ดีที่สุด ในขณะที่กระบวนการ (process) ยังเปิดไฟล์นั้นอยู่ inode และบล็อกข้อมูลจะยังคงถูกจัดสรรไว้ ทำให้ยังสามารถอ่านข้อมูลได้ ห้ามรีสตาร์ทบริการนั้น เพราะการปิด descriptor สุดท้ายจะทำให้การลบเสร็จสมบูรณ์ ให้รัน sudo lsof +L1 เพื่อแสดงรายการไฟล์ที่เปิดอยู่ซึ่งมีจำนวนลิงก์เป็น 0 จากนั้นจด PID และหมายเลข file descriptor ไว้ แล้วคัดลอกข้อมูลผ่าน /proc ด้วย sudo cp /proc/1234/fd/3 /mnt/rescue/events.log ให้เขียนไฟล์ที่คัดลอกไปยังระบบไฟล์อื่น รายการที่แสดงด้วย mem แทนหมายเลข descriptor คือไฟล์ที่ถูก memory mapped ไว้ ซึ่งไม่มีพาธ /proc/<pid>/fd ให้คัดลอก
ทำไมจึงควรทำอิมเมจของดิสก์แทนการรันเครื่องมือกู้คืนบนดิสก์โดยตรง?
เพราะเครื่องมือทุกชนิดต้องเขียนผลลัพธ์ลงที่ใดที่หนึ่ง และการเขียนลงบนระบบไฟล์ที่คุณกำลังกู้คืนอาจไปทับบล็อกว่างที่ยังมีข้อมูลของคุณอยู่ ให้คัดลอกพาร์ทิชันไปยังอุปกรณ์อื่นก่อนด้วย sudo ddrescue -n /dev/vdb1 /mnt/rescue/vdb1.img /mnt/rescue/vdb1.map แล้วจึงชี้ photorec ไปที่ไฟล์อิมเมจนั้น อิมเมจยังช่วยให้คุณลองใช้เครื่องมือตัวที่สองกับข้อมูลชุดเดิมได้ ซึ่งเป็นไปไม่ได้หากมีบางอย่างเขียนทับข้อมูลต้นฉบับไปแล้ว
คำสั่ง rm -rf / ยังคงทำลายระบบ Linux ได้หรือไม่?
คำสั่งเปล่าๆ ไม่สามารถทำได้ GNU rm จะปฏิเสธคำสั่งและแสดง rm: it is dangerous to operate recursively on '/' รูปแบบที่อันตรายคือรูปแบบที่มาในทางอื่น rm -rf "$TARGET"/* ที่มี TARGET ไม่ถูกตั้งค่าจะขยายผลเป็น rm -rf /* และเชลล์จะส่งรายการไดเรกทอรีระดับบนสุดจริงให้ rm ซึ่งไม่มีรายการใดที่เป็น / ทำให้ระบบป้องกันไม่ทำงาน ให้เขียน "${TARGET:?TARGET is not set}" แทน แล้วเชลล์จะหยุดทำงานก่อนที่ rm จะเริ่มรัน
snapshot ของระบบไฟล์ถือเป็นข้อมูลสำรองหรือไม่?
ไม่ snapshot ของ btrfs หรือ ZFS อยู่ใน pool เดียวกับข้อมูลที่ปกป้อง ดังนั้นหากดิสก์เสียหรือ pool พัง ข้อมูลทั้งสองส่วนจะสูญหายไปพร้อมกัน snapshot ของ LVM มีปัญหาเพิ่มเติมคือขนาดที่คงที่ เมื่อเต็มแล้วเคอร์เนลจะทำให้มันเป็นโมฆะและเนื้อหาภายในจะหายไป snapshot เหมาะสำหรับการย้อนกลับการลบที่เพิ่งเกิดขึ้นเมื่อสองนาทีก่อน สำหรับกรณีอื่นทั้งหมด ให้เก็บคลังข้อมูลสำรองไว้บนฮาร์ดแวร์แยกต่างหาก