การลบไฟล์นับล้านไฟล์


38

ฉันมีคนเต็มไปด้วยภาพ gif นับล้าน มีคำสั่ง rm มากเกินไป

ฉันได้ลองใช้คำสั่ง find แบบนี้แล้ว:

find . -name "*.gif" -print0 | xargs -0 rm

ปัญหาคือมันทำให้เครื่องของฉันแย่มากและทำให้ลูกค้าต้องเสียเวลาเนื่องจากเซิร์ฟเวอร์

มีวิธีใดที่เร็วกว่าในการลบไฟล์ทั้งหมดเหล่านี้ ... โดยไม่ล็อคเครื่อง?


ฉัน "m อยู่ที่ประมาณ 6 gb / hr อัตราการลบโดยใช้คำสั่ง" nice find "ด้านล่างอาจใช้เวลา 48 ชั่วโมงในการกำจัดไฟล์ทั้งหมดสาเหตุที่เกิดขึ้นคือสคริปต์ b / ca scour ล้มเหลวฉันเลย "ขอบฟ้าเหตุการณ์" พร้อมคำสั่ง rm แล้วมันก็วิ่งออกไป

3
จะลบทั้ง dir ไม่เร็วเร็ว? ใช้เวลาเพียงแค่ออกมา "ดี" ไฟล์ก่อน nuking คนที่เหลือ ...
tucuxi

ทีนี้, ทุกไฟล์ไม่ดีตอนนี้, เพราะมันถูกย้ายไปที่ / dir_old, และฉัน remade the / dir. แต่จะไม่ rmdir ทำงานในข้อ จำกัด เช่นเดียวกับ rm *?

@Corepuncher: ฉันคาดหวังว่าจะลบไดเรกทอรีทั้งหมด (เช่นเดียวกับที่rm -rfจะเร็วกว่ามันคุ้มค่าลอง
Jason R

ฉันกำลังเรียกใช้ "rm -rf" บน dir ตอนนี้ทำงานมานานกว่า 20 นาทีแล้ว ... ยังไม่มีการเปลี่ยนแปลงขนาดของดิสก์ แต่มันก็ไม่ได้กลับรายการ "การโต้แย้งนานเกินไป" โดยอัตโนมัติเช่นกัน ปัญหาเพียงอย่างเดียวคือมันใช้ค้อนทุบเครื่องจักรของฉันและทำให้สิ่งอื่นช้า / ล้มเหลว ไม่แน่ใจว่าปล่อยทิ้งไว้นานเท่าใด

คำตอบ:


44

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

ใช้nice (1)เพื่อลดระดับความสำคัญของคำสั่ง

nice find . -name "*.gif" -delete

สำหรับกระบวนการ I / O-bound ที่ดี (1) อาจไม่เพียงพอ ตัวกำหนดตารางเวลาลินุกซ์คำนึงถึง I / O ไม่ใช่แค่ CPU แต่คุณอาจต้องการการควบคุม I / O ที่มีความสำคัญมากกว่า

ionice -c 2 -n 7 find . -name "*.gif" -delete

หากวิธีนี้ไม่ได้ผลคุณสามารถเพิ่มโหมดสลีปเพื่อทำให้ช้าลงได้

find . -name "*.gif" -exec sleep 0.01 \; -delete

3
ว้าว ... ไฟล์นับล้านไฟล์หยุดทำงาน. 1 s ... ต้องการหนึ่งวันสำหรับไฟล์ 864000 ไฟล์
glglgl

7
@glglgl เอาหละสมาร์ท ฉันเปลี่ยนการหมดเวลา :-P
John Kugelman สนับสนุน Monica

28
การนอนหลับอาจเป็นทางเลือกที่ดี แต่ก็ดีจะไม่ทำเพราะงานที่นี่คือ IO ที่ถูกผูกไว้ไม่ใช่ CPU ที่ถูกผูกไว้ คุณอาจลองใช้ไอนิซแทน โปรดสังเกตว่าถ้าการนอนหลับมีขนาดเล็กเกินไปมันจะไร้ประโยชน์
Matteo Italia

3
@glglgl: ประเด็นตรงที่ว่าถ้าคุณไม่ต้องการให้บริการขัดข้องบนเซิร์ฟเวอร์ที่คุณต้องไปช้าๆเวลาที่โค้ดนี้อยู่ที่นั่นเพื่อให้เซิร์ฟเวอร์ทำงานได้มีประโยชน์จริง ๆ กับดิสก์
Matteo Italia

1
+1 สำหรับการsleepเพิ่ม - ฉันมีปัญหากับเซิร์ฟเวอร์ที่สำลัก IO แม้จะใช้ionice -c 3อยู่ก็ตาม มันเพิ่มอย่างมีนัยสำคัญต่อเวลาที่ใช้ในการล้างไฟล์ (แน่นอน) แต่ฉันจะรอมากกว่าทำให้แอปพลิเคชันลง ...
Ola Tuvesson

22

เนื่องจากคุณใช้งาน Linux และงานนี้น่าจะเป็น I / O-bound ฉันขอแนะนำให้คุณใช้คำสั่ง I / O ตัวกำหนดตารางเวลาที่ไม่ทำงานโดยใช้ลำดับความสำคัญionice(1):

ionice -c3 find . -name '*.gif' -delete

xargsเมื่อเปรียบเทียบกับคำสั่งเดิมของคุณผมคิดว่านี้อาจจะว่างบางรอบการทำงานมากขึ้นโดยการหลีกเลี่ยงท่อ


@Braiam คุณหมายถึงอะไร? นี่ไม่ใช่find ... -execที่ที่เหมาะสม

โอ้ใช่ขอโทษ ความผิดฉันเอง. คุณแน่ใจว่ามีประสิทธิภาพใช่ไหม
Braiam

1
Well, find(1)การเรียกร้องเพื่อให้เอกสาร :) และควรจะชัดเจนว่าการปล่อยให้findตัวเองลบไฟล์นั้นมีประสิทธิภาพมากกว่าการฟอร์กrmคำสั่งสำหรับสิ่งนี้

1
ฉันได้ลองใช้หลายรุ่นที่แนะนำในโฟลเดอร์ที่มี 4 ล้านไฟล์บนเซิร์ฟเวอร์ที่ใช้งานจริงและอันนี้เป็นรุ่นเดียวที่ไม่สำลักระบบ ionice -c3ลด prio ให้ทำงานเมื่อ IO ไม่ได้ใช้งานมิฉะนั้นนี่จะสมบูรณ์แบบ โปรดทราบว่าเนื่องจาก-deleteไม่ใช่มาตรฐานสำหรับการค้นหาคุณสามารถทำเช่นเดียวกัน (รวมถึงข้อเสนอแนะที่ใช้งานได้) โดยใช้คำสั่งนี้: ionice -c 3 find . -name '*.gif' -exec echo {} \; -exec rm {} \;- ช้า แต่ไม่มี iowaits ของกระบวนการที่สำคัญ
Christopher Lörken

13

เลขที่

ไม่มีวิธีที่รวดเร็วกว่าคือ appart จากรูปแบบซอฟต์ของดิสก์ ไฟล์ถูกกำหนดให้กับ rm ในครั้งเดียว (ไม่เกินขีด จำกัด ของบรรทัดคำสั่ง, มันอาจถูกตั้งค่าเป็นxargs) ซึ่งดีกว่าการเรียก rm ในแต่ละไฟล์ ไม่เลยไม่มีทางเร็วขึ้นแน่นอน

การใช้nice(หรือreniceในกระบวนการทำงาน) ช่วยเพียงบางส่วนเท่านั้นเพราะนั่นคือสำหรับการกำหนดเวลาทรัพยากรCPUไม่ใช่ดิสก์! และการใช้งาน CPU จะต่ำมาก นี่เป็นจุดอ่อนของ linux - หากกระบวนการหนึ่ง "กิน" ดิสก์ (เช่นทำงานได้มากกับมัน) เครื่องทั้งหมดก็จะติดขัด เคอร์เนลดัดแปลงสำหรับการใช้งานแบบเรียลไทม์อาจเป็นทางออก

สิ่งที่ฉันจะทำบนเซิร์ฟเวอร์คือการอนุญาตให้กระบวนการอื่นทำงานด้วยตนเอง - รวมการหยุดชั่วคราวเพื่อให้เซิร์ฟเวอร์ "หายใจ":

find . -name "*.gif" > files
split -l 100 files files.
for F in files.* do
    cat $F | xargs rm
    sleep 5 
done

ขั้นตอนนี้จะรอ 5 วินาทีหลังจากทุก ๆ 100 ไฟล์ จะใช้เวลานานกว่า แต่ลูกค้าของคุณไม่ควรสังเกตเห็นความล่าช้าใด ๆ


"ไฟล์ถูกกำหนดให้ rm ในครั้งเดียว (สูงสุดถึงขีด จำกัด ของบรรทัดคำสั่ง" - ดังนั้นเมื่อเชลล์สั่งให้rm *มันขยาย*เข้าไปในบรรทัดด้วยชื่อไฟล์ทั้งหมดและส่งไปยังrmนั่นคือโง่อย่างไม่น่าเชื่อทำไมเปลือกขยาย wildcard หรือไม่

:-D @Joker_vD คุณล้อเล่นตามชื่อของคุณหรือเปล่า? :-)
Tomas

2
@Joker_vD: ความเข้ากันได้กับการตัดสินใจของ Unix ตั้งแต่ปี 1970 หรือมากกว่านั้น Windows ไม่ทำ ที่นั่นโปรแกรมสามารถส่งสัญลักษณ์แทนไปที่ FindNextFile / FindNextFile เพื่อให้พวกเขาได้รับผลลัพธ์ทีละรายการ
MSalters

@Tomas ไม่ใช่ในกรณีนี้ จริงๆแล้วฉันเห็นปัญหา 2 ประการในการออกแบบเช่นนี้ทันที: อันดับแรกบรรทัดคำสั่งไม่ใช่ยาง ประการที่สองโปรแกรมไม่สามารถบอกได้ว่ามันถูกเรียกด้วย*หรือ/*สงสัยในการตัดสินใจของผู้ใช้

1
@Joker_vD มีหลายสิ่งที่ดีเกี่ยวกับเชลล์ที่ทำการขยายตัวสัญลักษณ์ มันแตกต่างจาก Windows แต่อย่าข้ามไปที่ข้อสรุปว่ามันโง่อย่างไม่น่าเชื่อเพียงเพราะมันแตกต่างจากสิ่งที่คุณคุ้นเคย หากคุณต้องการทราบข้อมูลเพิ่มเติมฉันแนะนำให้คุณไปที่ Google หรือโพสต์คำถามบนเว็บไซต์ Stack Exchange ที่เกี่ยวข้อง มันเป็นเรื่องใหญ่สำหรับพื้นที่ความคิดเห็นนี้
John Kugelman สนับสนุน Monica

5

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

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

จะมีการหยุดทำงาน แต่อาจดีกว่าประสิทธิภาพที่ไม่ดีอย่างต่อเนื่องและการหยุดชะงักของบริการ

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

ตัวอย่างเช่นสมมติว่าคุณต้องการลบไฟล์ทั้งหมดในระบบไฟล์ อะไรคือประเด็นของการเรียกซ้ำและการลบทีละตัว? เพียงเลิกเมานท์และทำ "mkfs" ที่ด้านบนของพาร์ติชันเพื่อสร้างระบบไฟล์เปล่า

หรือสมมุติว่าคุณต้องการลบไฟล์ทั้งหมดยกเว้นไฟล์สำคัญครึ่งโหล? รับครึ่งโหลออกจากที่นั่นและ ... "mkfs" ด้านบน

ในที่สุดก็มีบางจุดคุ้มทุนเมื่อมีไฟล์เพียงพอที่จะอยู่ที่มันจะถูกกว่าที่จะทำการลบซ้ำโดยคำนึงถึงต้นทุนอื่น ๆ เช่นการหยุดทำงานใด ๆ


4

คุณเคยลองไหม:

find . -name "*.gif" -exec rm {} +

เครื่องหมาย + ที่ส่วนท้ายจะทำให้การค้นหารวมไฟล์มากขึ้นเพื่อให้คำสั่ง rm เดียวถูกเรียกใช้งาน ตรวจสอบคำถามนี้เพื่อดูรายละเอียดเพิ่มเติม


มันรันเร็วกว่า -print0 | โซลูชัน xargs เนื่องจากกระบวนการ rm ไม่ได้ถูกเรียกใช้สำหรับทุกไฟล์ แต่สำหรับชุดไฟล์ขนาดใหญ่ดังนั้นจึงทำให้โหลดต่ำลง

@JohnKugelman คุณถูกต้อง แต่เป็นส่วนขยาย GNU ที่ไม่สามารถใช้งานได้ตลอดเวลากับคำสั่งnative find
CodeGnome

ตกลงน่าสนใจ แต่นี่เป็นสิ่งที่ค่อนข้างใหม่ (รวมถึง-delete) ซึ่งไม่จำเป็นต้องอยู่ที่นั่นเสมอไป ..
Tomas

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