วิธีทำความสะอาดโฟลเดอร์ tmp อย่างปลอดภัยบน Linux


15

ฉันใช้ RAM สำหรับ tmpfs / tmp, 2GB ของฉันเป็นที่แน่นอน โดยปกติจะเพียงพอ แต่บางครั้งกระบวนการสร้างไฟล์ในนั้นและล้มเหลวในการล้างข้อมูลหลังจากตัวเอง สิ่งนี้สามารถเกิดขึ้นได้หากเกิดปัญหา ฉันจำเป็นต้องลบไฟล์ tmp ที่กำพร้ามิฉะนั้นกระบวนการในอนาคตจะหมดพื้นที่บน / tmp

ฉันจะเก็บขยะ / tmp อย่างปลอดภัยได้อย่างไร บางคนทำโดยการตรวจสอบการประทับเวลาการปรับเปลี่ยนครั้งล่าสุด แต่วิธีการนี้ไม่ปลอดภัยเนื่องจากอาจมีกระบวนการที่ใช้เวลานานซึ่งยังต้องการไฟล์เหล่านั้น วิธีที่ปลอดภัยกว่าคือการรวมเงื่อนไขการประทับเวลาการแก้ไขครั้งล่าสุดกับเงื่อนไขที่ไม่มีกระบวนการใดที่มีการจัดการไฟล์สำหรับไฟล์ มีโปรแกรม / สคริปต์ / etc ที่รวบรวมแนวทางนี้หรือวิธีอื่นที่ปลอดภัยหรือไม่

อนึ่ง Linux / Unix อนุญาตโหมดการเปิดไฟล์ที่มีการสร้างไฟล์นั้นถูกลบหรือไม่เมื่อกระบวนการสร้างสิ้นสุดลงแม้ว่าจะเกิดจากความผิดพลาดหรือไม่?


ตรวจสอบว่าคุณสามารถใช้ tmpfs แทน / tmp: kernel.org/doc/Documentation/filesystems/tmpfs.txt
ott--

คำตอบ:


15

คุณอาจต้องการลองทำสิ่งต่อไปนี้:

find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'

find ใช้เพื่อค้นหาไฟล์ที่ตรงกับเกณฑ์ที่กำหนด

  • -mtime +7 เลือกไฟล์ที่เก่ากว่า 7 วันเท่านั้น (คุณสามารถใช้ค่าอื่น ๆ ได้)
  • -exec fuser -s {} ';'เรียก fuser ในโหมดไม่ต้องป้อนข้อมูลสำหรับทุกไฟล์ที่ตรงกับเกณฑ์ความเก่า fuser ส่งกลับค่า 0 (= true) สำหรับทุกไฟล์ที่เข้าถึงได้ในขณะนี้และ 1 (= false) สำหรับไฟล์ที่ไม่สามารถเข้าถึงได้ เนื่องจากเราสนใจเฉพาะสิ่งที่ไม่สามารถเข้าถึงได้เราจึงกล่าวถึง-notเรื่องนี้-exec
  • -exec echo {} ';'เพียงพิมพ์ชื่อไฟล์ทั้งหมดที่ตรงกับเกณฑ์ คุณอาจต้องการใช้-exec rm {} ';'แทนที่นี่ แต่เนื่องจากอาจลบไฟล์ที่ยังใช้งานอยู่บางอย่างฉันคิดว่าการทำเสียงก้องง่ายกว่าปลอดภัยกว่าก่อน
  • แก้ไข:คุณอาจต้องการเพิ่มสิ่งที่ชอบ-name 'foo*.bar'หรือ-uid 123จำกัด ผลกระทบของการล้างข้อมูลให้กับรูปแบบไฟล์หรือ ID ผู้ใช้เฉพาะเพื่อหลีกเลี่ยงผลกระทบโดยไม่ตั้งใจ

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

edit2: สำหรับคำถามสุดท้ายของคุณ: ไฟล์จะไม่ถูกลบออกจากดิสก์จนกว่าจะไม่มีกระบวนการใด ๆ ที่มีการจัดการแบบเปิด (อย่างน้อยสำหรับระบบไฟล์ linux ดั้งเดิม) ปัญหาคือรายการไดเรกทอรีจะถูกลบทันทีซึ่งหมายความว่าตั้งแต่เวลาที่คุณลบไฟล์ไม่มีกระบวนการใหม่สามารถเปิดไฟล์ได้อีกต่อไป (เนื่องจากไม่มีชื่อไฟล์แนบอยู่)

ดูรายละเอียดได้ที่: /programming/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux

edit3:แต่ถ้าฉันต้องการทำให้กระบวนการทั้งหมดเป็นแบบอัตโนมัติล่ะ

อย่างที่ฉันบอกไปแล้วอาจมีไฟล์ที่เขียนครั้งเดียวแล้วอ่านทุก ๆ ครั้ง (เช่นคุกกี้เซสชัน X, ไฟล์ PID ฯลฯ ) สิ่งเหล่านี้จะไม่ถูกแยกออกจากสคริปต์ลบขนาดเล็กนี้ (ซึ่งเป็นสาเหตุที่คุณอาจต้องทำการทดสอบechoก่อนก่อนที่จะลบไฟล์)

วิธีหนึ่งในการนำโซลูชันที่ปลอดภัยมาใช้atimeคือ
atimeเก็บเวลาที่เข้าถึงไฟล์แต่ละครั้งล่าสุด แต่ตัวเลือกระบบไฟล์นั้นมักจะถูกปิดการใช้งานเพราะมันมีผลกระทบต่อประสิทธิภาพค่อนข้างมาก (ตามบล็อกนี้อยู่ที่ไหนสักแห่งในภูมิภาค 20-30%) มีrelatimeแต่มีหนึ่งเขียนเวลาเข้าถึงหากmtimeมีการเปลี่ยนแปลงดังนั้นอันนี้จะไม่ช่วยเรา

หากคุณต้องการใช้atimeฉันขอแนะนำให้/tmpใช้พาร์ติชันแยกต่างหาก (เป็น ramdisk) เพื่อให้ประสิทธิภาพการทำงานของทั้งระบบไม่ใหญ่เกินไป

เมื่อatimeมีการใช้งานทั้งหมดที่คุณต้องทำคือการเปลี่ยนพารามิเตอร์ในบรรทัดคำสั่งข้างต้นด้วย-mtime คุณอาจจะสามารถลบได้แต่ฉันจะเก็บไว้ที่นั่นเพื่อให้แน่ใจ (ในกรณีที่แอปพลิเคชันเปิดไฟล์ไว้เป็นระยะเวลานาน)-atime
-not -exec fuser -s {} ';'

แต่โปรดจำไว้ว่าให้ทดสอบคำสั่งที่ใช้echoก่อนที่คุณจะลบสิ่งที่ระบบของคุณต้องการ!


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

นั่นคือปัญหาของวิธีการนี้ (ตามที่ฉันได้ชี้ให้เห็นในวรรคสุดท้าย) วิธีที่ดีที่สุดที่นี่ AFAIK จะเพิ่ม UID / GID หรือการตรวจสอบรูปแบบไฟล์ (แก้ไขคำตอบตาม)
mreithub

สิ่งนี้ควรอยู่ในสคริปต์ cron หรือไม่?
CMCDragonkai

@CMCDragonkai แน่นอนคุณสามารถใส่สิ่งนี้ลงใน crontab แต่อย่างที่ฉันพูดถึงอาจจะมีไฟล์ที่เข้าถึง แต่ไม่ได้เขียนดังนั้นอาจไม่ถูกกรองออกโดยสคริปต์เล็ก ๆ นี้ นั่นเป็นเหตุผลที่ปลอดภัยกว่าที่จะพิมพ์รายการไฟล์ที่ได้รับผลกระทบก่อนแล้วตัดสินใจด้วยตัวเองว่าจะลบออกหรือไม่ หากคุณ/tmpอยู่ในพาร์ติชันแยกต่างหาก (เช่น ramdisk) คุณสามารถเปิดใช้atimeงานได้และใช้-atimeพารามิเตอร์findเป็น
mreithub

ฉันวางแผนที่จะทำสิ่งนี้บนเซิร์ฟเวอร์ ดังนั้นฉันไม่สามารถอยู่ที่นั่นเพื่อนับไฟล์ทั้งหมดใน tmp ตลอดเวลา จะมีปัญหาอะไรไหม? นอกจากนี้ฉันคิดว่าเราตั้งใจจะใช้ relatime ไม่ใช่ atime?
CMCDragonkai

4

อย่าม้วนตัวคุณเอง

Debian / Ubuntu มี tmpreaper มันอาจมีวางจำหน่ายในส่วนอื่นเช่นกัน

# tmpreaper - cleans up files in directories based on their age

sudo apt-get install tmpreaper

cat /etc/tmpreaper.conf 

ใน/etc/tmpreaper.confไฟล์ถ้าฉันตั้งค่าทั้งสอง/tmpและ/var/tmpเป็นไดเรกทอรีการล้างข้อมูลคุณสามารถแนะนำTMPREAPER_TIMEพารามิเตอร์หรือไฟล์ tmp สูงสุดที่ผ่านมานานเท่าใดให้ลบออกได้หรือไม่ ฉันได้ยินมาว่าดีกว่าที่จะเก็บ/var/tmpไฟล์ไว้นานกว่า/tmpไฟล์ แต่ถ้าพวกเขาสามารถตั้งค่าด้วยอายุสูงสุดเท่ากันฉันไม่มีเงื่อนงำ
Xiaodong Qi

2

เกี่ยวกับคำถามสุดท้ายของคุณ:

แม้ว่าฉันจะไม่คิดว่ามีโหมดเปิด / สร้าง 'ลบ-this-if-I-die' อยู่ แต่กระบวนการสามารถลบไฟล์ได้อย่างปลอดภัยหลังจากสร้างมันขึ้นมาอย่างปลอดภัยตราบใดที่ยังเปิดหมายเลขอ้างอิงไว้ เคอร์เนลจะเก็บไฟล์ไว้ในดิสก์และทันทีที่กระบวนการสุดท้ายที่เปิดไฟล์ออก (ไม่ว่าจะเกิดจากความผิดพลาดหรือตามปกติ) พื้นที่ที่ไฟล์ครอบครองจะถูกปล่อยให้เป็นอิสระ

สำหรับลักษณะทั่วไปแก้ไขปัญหาที่กระบวนการบางอย่างบางครั้งไม่ได้ทำความสะอาด / tmp ผมจะแนะนำให้มีลักษณะที่ติด namespaces อธิบายเช่นที่นี่หรือที่นี่ หากกระบวนการที่ต้องสงสัยคือ daemon ของระบบsystemdและคุณลักษณะดั้งเดิมเพื่ออนุญาตให้ระบบไฟล์ส่วนตัว / tmp อาจเป็นที่สนใจ



0

รับรายการไฟล์ที่เก่ากว่าดังนั้นแยกไฟล์ที่เปิดโดยอะไรจากรายการนั้น:

find /tmp -mtime +7 |\
    egrep -v "`lsof -n +D /tmp | awk 'NR>1 {print $9}'| tr \\n \|`" 

lsof -n +D /tmp: ค้นหาไฟล์ที่เปิดอยู่ใน / tmp
awk 'NR>1 {print $9}': พิมพ์เฉพาะคอลัมน์ที่เก้าของเอาต์พุต lsof ยกเว้นส่วนหัว
tr \\n \|: แทนที่บรรทัดใหม่ด้วยแถบ (หรือใน egrep)
egrep -v "foo|moo|bar": พิมพ์บรรทัดที่ไม่มี foo หรือ moo หรือ bar


0

ฉันเห็นด้วยกับข้างต้นเพื่อเพิ่มมัน - ฉันมักจะเรียกใช้lsof +L1 | grep tmpและฆ่าหรือรีสตาร์ทกระบวนการถือเพื่อ "ลบ" ไฟล์ tmp: ตัวอย่าง -

# lsof +L1 | grep tmp
xfce4-ter  1699  user   32u   REG    8,6      192     0 818552 /tmp/vte966VLX (deleted)
chrome     3301  user  138u   REG    8,6    16400     0 818547 /tmp/etilqs_Z0guKD7p6ork9iG (deleted)

2
SU สุ่มเรียงโพสต์ - ดังนั้นจึงไม่มีด้านบนหรือด้านล่าง คุณหมายถึงโพสต์ใด
Geek

0

คุณทำได้rm -rf /tmp/*และหวังว่าจะไม่มีอะไรหยุดพัก ...


1
เสนอแนะให้ทำอะไร "และหวังว่าแบ่งอะไร" ไม่ได้โดดตอบของ OP "คือมีวิธีที่ปลอดภัยที่จะทำเช่นนี้คุณอาจอธิบายรายละเอียดว่าทำไมข้อเสนอแนะของคุณจะปลอดภัย.
bertieb

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