ค้นหาและลบไฟล์ขนาดใหญ่ที่เปิดอยู่ แต่ถูกลบไปแล้ว


120

จะพบไฟล์ขนาดใหญ่ที่ถูกลบ แต่ยังคงเปิดอยู่ในแอปพลิเคชั่นได้อย่างไร? เราจะลบไฟล์นั้นออกได้อย่างไรแม้ว่ากระบวนการจะเปิดขึ้นมาก็ตาม

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

เพียงแค่ทำการrm output.logลบการอ้างอิงไปยังไฟล์เท่านั้น แต่จะยังคงใช้พื้นที่บนดิสก์ต่อไปจนกว่ากระบวนการจะสิ้นสุดลง แย่ลง: หลังจากrmวันนี้ฉันไม่มีทางที่จะค้นหาไฟล์หรือว่ามันใหญ่แค่ไหน! มีวิธีใดในการค้นหาไฟล์และอาจทำให้มันว่างเปล่าแม้ว่ามันจะยังคงเปิดอยู่ในกระบวนการอื่นหรือไม่?

ฉันอ้างถึงระบบปฏิบัติการบน Linux เป็นพิเศษเช่น Debian หรือ RHEL


2
หากคุณรู้จัก pid คุณสามารถใช้lsof -p <pid>เพื่อแสดงรายการไฟล์ที่เปิดและขนาดไฟล์ ไฟล์ที่ถูกลบจะมีไฟล์(deleted)อยู่ข้างๆ ไฟล์ที่ถูกลบจะถูกลิงค์ที่/proc/<pid>/fd/1อาจเป็นไปได้ ฉันไม่ทราบวิธีที่จะทำให้กระบวนการหยุดเขียนลงไฟล์ descriptor ของมันโดยไม่ยกเลิก ฉันคิดว่าจะขึ้นอยู่กับกระบวนการ
donothingsuccessfully

ขอบคุณ เราจะได้รับ PID ของrmไฟล์ ed ทั้งหมดที่ยังคงเปิดอยู่ได้อย่างไร
dotancohen

@donothingsuccessfully แท็ก "ลบ" ที่รายงานโดย lsof เป็นข้อมูลเฉพาะของ Solaris ในความเป็นจริง Solaris 10 หรือใหม่กว่าเท่านั้น OP ไม่ได้ระบุระบบปฏิบัติการที่ใช้ @dotancohen บน Solaris คุณสามารถท่อส่งออกของ lsof lsof | grep "(deleted)"เพื่อค้นหาลบเช่น เมื่อไม่มีกระบวนการที่เปิดไฟล์ที่ถูกลบอีกต่อไปเคอร์เนลจะทำให้ inode และดิสก์บล็อกว่าง กระบวนการไม่มี "ตัวจัดการ" ซึ่งพวกเขาสามารถได้รับการแจ้งเตือนว่าไฟล์ที่เปิดและถูกล็อคเป็นหลักได้ถูกลบออกจากดิสก์
Johan

2
@Janan lsof | grep '(deleted)'ทำงานบน Linux ได้เช่นกัน บน Linux คุณสามารถได้รับแจ้งถึงการลบไฟล์ (แม้แต่ไฟล์ที่ไม่มีรายการในไดเรกทอรีอื่นที่ไม่ใช่ / proc / some-pid / fd อีกต่อไป) ด้วยกลไก inotify (เหตุการณ์ IN_DELETE_SELF)
Stéphane Chazelas

ฉันสร้างsomefileและเปิดใน VIM จากนั้นทำการrmแก้ไขในกระบวนการทุบตีอีกครั้ง ฉันเรียกใช้แล้วlsof | grep somefileและมันไม่ได้อยู่ในนั้นแม้ว่าไฟล์จะเปิดใน VIM
dotancohen

คำตอบ:


141

หากคุณไม่สามารถฆ่าแอปพลิเคชันของคุณคุณสามารถตัดทอนแทนการลบไฟล์บันทึกเพื่อเรียกคืนพื้นที่ หากไฟล์ไม่ได้เปิดในโหมดต่อท้าย (พร้อมO_APPEND) ไฟล์นั้นจะปรากฏใหญ่เหมือนก่อนครั้งต่อไปที่แอปพลิเคชันเขียนลงไป (แม้ว่าจะมีส่วนนำหน้ากระจัดกระจายและดูราวกับว่ามี NUL ไบต์) แต่พื้นที่ จะถูกเรียกคืน (ซึ่งไม่สามารถใช้กับระบบไฟล์ HFS + บน Apple OS / X ที่ไม่รองรับไฟล์แบบกระจาย)

วิธีตัดทอน:

: > /path/to/the/file.log

หากถูกลบไปแล้วบน Linux คุณยังสามารถตัดทอนได้โดยทำดังนี้:

: > "/proc/$pid/fd/$fd"

ที่ไหน$pidเป็นกระบวนการ id ของกระบวนการที่มีไฟล์ที่เปิดและ$fdหนึ่งอธิบายไฟล์มันมีมันเปิดอยู่ภายใต้ lsof -p "$pid"(ซึ่งคุณสามารถตรวจสอบกับ

หากคุณไม่รู้จัก pid และกำลังมองหาไฟล์ที่ถูกลบคุณสามารถทำได้:

lsof -nP | grep '(deleted)'

lsof -nP +L1, ดังกล่าวโดย @ user75021เป็นดียิ่งขึ้น (ความน่าเชื่อถือและการพกพามากขึ้น) ตัวเลือก (ไฟล์รายการที่มีน้อยกว่า 1 ลิงค์)

หรือ (บน Linux):

find /proc/*/fd -ls | grep  '(deleted)'

หรือเพื่อค้นหาสิ่งที่มีขนาดใหญ่ด้วยzsh:

ls -ld /proc/*/fd/*(-.LM+1l0)

ทางเลือกถ้าโปรแกรมมีการเชื่อมโยงแบบไดนามิกคือการแนบดีบักเกอร์กับมันและทำให้มันโทรตามด้วยใหม่close(fd)open("the-file", ....)


1
นอกจากนี้ยังมีtruncateคำสั่งที่ทำสิ่งเดียวกันอย่างชัดเจนยิ่งขึ้น
Tobu

1
@dancancohen Stephane แก้ไขเพื่อรวมข้อมูลเกี่ยวกับวิธีการทำเช่นนี้เมื่อ pid ไม่เป็นที่รู้จัก
Didi Kohen

1
@OlivierDulac lsofน่าจะใกล้เคียงกับโซลูชันแบบพกพามากที่สุดคุณสามารถไปยังรายการไฟล์ที่เปิดอยู่ได้ วิธีการดีบักเกอร์เพื่อปิด fd ภายใต้ฟุตแอพพลิเคชั่นควรเป็นแบบพกพาเช่นกัน
Stéphane Chazelas

2
@StephaneChazelas: ขอบคุณ ฉันพบวิธีที่จะแสดงรายการ PID ทั้งหมดที่มีไฟล์เปิดอยู่ในแต่ละพาร์ติชัน: df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud (และจากนั้นง่ายที่จะส่งสัญญาณไปยังผู้ที่กระทำผิดเพื่อบังคับให้พวกเขาปล่อย fd)
Olivier Dulac

6
lsof +L1นอกจากนี้คุณยังสามารถใช้ จากหน้า lsof man: "ข้อมูลจำเพาะของแบบฟอร์ม+L1จะเลือกไฟล์เปิดที่ไม่ได้เชื่อมโยงข้อมูลจำเพาะของแบบฟอร์ม+aL1 <file_system>จะเลือกไฟล์ที่ไม่ได้เชื่อมโยงเปิดในระบบไฟล์ที่ระบุ" นั่นควรจะเชื่อถือได้มากกว่า grepping สักหน่อย
ซิงโคร

31

ลองดู quickstart ที่นี่: lsofQuickstart

ฉันประหลาดใจที่ไม่มีใครพูดถึงไฟล์ quickstart lsof (รวมอยู่ใน lsof) ส่วน "3.a" แสดงวิธีค้นหาไฟล์ที่เปิดและไม่เชื่อมโยง:

lsof -a +L1 *mountpoint*

เช่น:

[root@enterprise ~]# lsof -a +L1 /tmp
COMMAND   PID   USER   FD   TYPE DEVICE    SIZE NLINK  NODE NAME
httpd    2357 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
mysqld   2588  mysql    4u   REG 253,17      52     0  1495 /tmp/ibY0cXCd (deleted)
mysqld   2588  mysql    5u   REG 253,17    1048     0  1496 /tmp/ibOrELhG (deleted)
mysqld   2588  mysql    6u   REG 253,17       0     0  1497 /tmp/ibmDFAW8 (deleted)
mysqld   2588  mysql    7u   REG 253,17       0     0 11387 /tmp/ib2CSACB (deleted)
mysqld   2588  mysql   11u   REG 253,17       0     0 11388 /tmp/ibQpoZ94 (deleted)
httpd    3457   root   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8437 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8438 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8439 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8440 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8441 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8442 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8443 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8444 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   16990 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   19595 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   27495 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   28142 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   31478 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)

ในระบบ Red Hat เพื่อค้นหาสำเนาโลคัลของไฟล์ quick-start ฉันมักทำสิ่งนี้:

[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART

... หรือสิ่งนี้:

[root@enterprise ~]# rpm -qd lsof
/usr/share/doc/lsof-4.78/00.README.FIRST
/usr/share/doc/lsof-4.78/00CREDITS
/usr/share/doc/lsof-4.78/00DCACHE
/usr/share/doc/lsof-4.78/00DIALECTS
/usr/share/doc/lsof-4.78/00DIST
/usr/share/doc/lsof-4.78/00FAQ
/usr/share/doc/lsof-4.78/00LSOF-L
/usr/share/doc/lsof-4.78/00MANIFEST
/usr/share/doc/lsof-4.78/00PORTING
/usr/share/doc/lsof-4.78/00QUICKSTART
/usr/share/doc/lsof-4.78/00README
/usr/share/doc/lsof-4.78/00TEST
/usr/share/doc/lsof-4.78/00XCONFIG
/usr/share/man/man8/lsof.8.gz

1

มันขึ้นอยู่กับโปรแกรมควบคุมระบบไฟล์ที่จริงฟรีพื้นที่จัดสรรและที่มักจะเกิดขึ้นเพียงครั้งเดียวทั้งหมดอธิบายไฟล์หมายถึงไฟล์ที่ถูกปล่อยออกมา ดังนั้นคุณไม่สามารถเรียกคืนพื้นที่จริง ๆ ได้เว้นแต่คุณจะทำให้แอปพลิเคชันปิดไฟล์ ซึ่งหมายถึงการยกเลิกหรือเล่นกับ "บิต" ในโปรแกรมดีบั๊ก (เช่นปิดไฟล์และตรวจสอบให้แน่ใจว่าไม่ได้เปิด / เขียนไปยังอีกหรือเปิด/dev/nullแทน) หรือคุณสามารถแฮกเคอร์เนล แต่ฉันอยากจะแนะนำว่า

การตัดไฟล์เป็น Stephane แนะนำอาจช่วยได้ แต่ผลลัพธ์ที่แท้จริงจะขึ้นอยู่กับระบบไฟล์ของคุณ (เช่นบล็อกที่จัดสรรล่วงหน้าจะมีแนวโน้มที่จะเป็นอิสระหลังจากคุณปิดไฟล์ในกรณีใด ๆ )

เหตุผลที่อยู่เบื้องหลังพฤติกรรมนี้คือเคอร์เนลไม่รู้ว่าจะทำอย่างไรกับการร้องขอข้อมูล (ทั้งการอ่านและการเขียน แต่การอ่านนั้นสำคัญยิ่งกว่า) การกำหนดเป้าหมายไฟล์ดังกล่าว


2
เนื่องจาก Linux สนับสนุนไฟล์ที่กระจัดกระจายในระบบไฟล์ส่วนใหญ่ลักษณะการทำงานจะถูกกำหนดไว้อย่างดีและไดรเวอร์ดิสก์สามารถเพิ่มพื้นที่ว่างในดิสก์ได้ ฉันได้ทดสอบมันสำหรับ ext3 และ ext4 และทำงานเหมือน Stephane เขียน
jofel

1
อะไรทำให้คุณพูดว่าการตัดไฟล์จะไม่เรียกคืนบล็อกที่จัดสรรล่วงหน้า การตัดทอนมีขึ้นเพื่อยกเลิกการจัดสรรข้อมูลฉันไม่ได้มีอะไรคลุมเครือในเรื่องนี้
Stéphane Chazelas

1
ระบบไฟล์อาจเก็บบล็อกที่จัดสรรไว้เพื่อประหยัดเวลาในภายหลัง (โดยเฉพาะถ้าไฟล์ยังคงเปิดอยู่) โดยเฉพาะเมื่อมันใหญ่พอก่อนที่จะตัดทอน อย่างน้อยนั่นคือสิ่งที่ XFS ดูเหมือนว่าจะทำ
peterph

ขอบคุณปีเตอร์ ฉันดีใจที่คุณพูดถึง "ทำไม" ในโพสต์นี้
dotancohen

2
เท่าที่ฉันสามารถบอกได้การตัดทอนไฟล์ที่เปิดอยู่จะเรียกคืนพื้นที่บน XFS เช่นกัน ทดสอบกับไฟล์ปกติและไฟล์ที่จัดสรรด้วยfallocateบน Linux 4.9 คุณช่วยอธิบายให้ชัดเจนด้วยระบบไฟล์และเงื่อนไขที่ตัดทอนไฟล์ไม่ได้เรียกคืนพื้นที่ได้หรือไม่?
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.