Cách xóa hàng triệu tệp mà không làm phiền máy chủ


11

Tôi muốn xóa một thư mục bộ đệm nginx, mà tôi đã nhanh chóng thanh trừng bằng:

mv cache cache.bak
mkdir cache
service nginx restart

Bây giờ tôi có một cache.bakthư mục có 2 triệu tệp. Tôi muốn xóa nó, mà không làm phiền máy chủ.

Một rm -rf cache.bakmáy chủ đơn giản làm hỏng máy chủ, ngay cả phản hồi HTTP đơn giản nhất cũng mất 16 giây trong khi rm đang chạy, vì vậy tôi không thể làm điều đó.

Tôi đã cố gắng ionice -c3 rm -rf cache.bak, nhưng nó không giúp được gì. Máy chủ có ổ cứng, không phải ổ SSD, có lẽ trên ổ SSD, đây có thể không phải là vấn đề.

Tôi tin rằng giải pháp tốt nhất sẽ là một số điều tiết lưu, giống như cách trình quản lý bộ đệm được tích hợp trong nginx.

Làm thế nào bạn sẽ giải quyết điều này? Có công cụ nào có thể làm chính xác điều này?

ext4 trên Ubuntu 16.04


1
Làm thế nào bạn phục hồi từ "rm -rf cache.bak"? Có vẻ như nginx đã chạy khi bạn đổi tên, vì vậy nó có thể đã duy trì các mô tả tệp và thậm chí chuyển sang thư mục mới. Tôi nghĩ bạn cần tắt nginx hoàn toàn, xóa bộ nhớ cache, sau đó khởi động lại.
Jan Steinman

6
Trong tương lai, vui lòng dán bộ nhớ cache của bạn trên một hệ thống tệp riêng biệt. Bằng cách đó, bạn có thể đơn giản nuke hệ thống tập tin đó, nhanh hơn nhiều so với việc cố gắng xóa hàng triệu tệp. Đã học được điều này một cách khó khăn một vài năm trước đây với một thư mục bộ đệm hylafax chứa hàng trăm tập tin.
Dennis Kaarsemaker

Bạn đã thử chạy rmbằng cách sử dụng tốt đẹp ?
Vladislav Rastrusny

Hãy thử rsync để xóa nhanh - câu trả lời cho trường hợp tương tự - unix.stackexchange.com/questions/37329/ mẹo
kawu

Cảm ơn tất cả các ý kiến, tôi đã tóm tắt những phát hiện của tôi để viết câu trả lời.
hyperknot

Câu trả lời:


9

Tạo một kịch bản bash như thế này:

#!/bin/bash
rm -- "$*"
sleep 0.5

Lưu nó với tên deleter.shchẳng hạn. Chạy chmod u+x deleter.shđể làm cho nó thực thi.

Kịch bản lệnh này xóa tất cả các tệp được truyền cho nó dưới dạng đối số và sau đó ngủ 0,5 giây.

Sau đó, bạn có thể chạy

find cache.bak -print0 | xargs -0 -n 5 deleter.sh

Lệnh này lấy danh sách tất cả các tệp trong cache.bak và chuyển năm tên tệp cùng một lúc cho tập lệnh xóa.

Vì vậy, bạn có thể điều chỉnh số lượng tệp bị xóa cùng một lúc và độ trễ giữa mỗi lần thao tác xóa.


Cảm ơn giải pháp này, tôi đã đưa nó vào bài viết tổng thể của mình. Một câu hỏi mặc dù, làm thế nào là xử lý ns lớn này? Tôi thường gặp vấn đề với ký tự * trong các thư mục lớn có lỗi, không phải vậy sao?
hyperknot

xargshiểu kích thước tối đa của một dòng lệnh và cố gắng không vượt quá nó theo mặc định. Điều này có giới hạn bổ sung không quá 5 đường dẫn cùng một lúc.
BowlOfRed

1
Chỉ cần lưu ý rằng với tốc độ 10 tệp mỗi giây, sẽ mất 55 giờ để xóa 2 triệu tệp.
Andrew Henle

4

Bạn nên xem xét việc lưu bộ nhớ cache của mình trên một hệ thống tệp riêng biệt mà bạn có thể gắn kết / ngắt kết nối như ai đó đã nêu trong các nhận xét. Cho đến khi bạn làm điều đó, bạn có thể sử dụng một lớp lót này /usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -deletegiả sử nhị phân tìm thấy của bạn nằm dưới / usr / bin và bạn muốn xem tiến trình trên màn hình. Điều chỉnh giấc ngủ phù hợp để bạn không quá căng thẳng.


Không cần -print0ở đây, vì bạn không đặt đầu ra ở findbất cứ đâu.
Tero Kilkanen

Bạn có thể quan tâm đến những gì rm-ing. Gọi nó là hoang tưởng, nhưng tôi luôn muốn chắc chắn rằng tôi đang xóa đúng tệp.
Alex

À đúng rồi, tôi đã không giải mã được lệnh một cách chính xác, thật tệ.
Tero Kilkanen

3

Bạn có thể muốn thử ionice trên một tập lệnh tiêu thụ đầu ra của lệnh find. Một cái gì đó như sau:

ionice -c3 $(
for file in find cache.bak -type f; do
    rm $file
done
for dir in find cache.bak -depthe -type d -empty; do
    rmdir $dir
done
)

Tùy thuộc vào hệ thống tệp, mỗi lần xóa tệp có thể dẫn đến việc viết lại toàn bộ thư mục đó. Đối với các thư mục lớn có thể là một hit. Có các cập nhật bổ sung cần thiết cho bảng inode và có thể là danh sách không gian trống.

Nếu hệ thống tập tin có một tạp chí, những thay đổi được ghi vào tạp chí; áp dụng; và loại bỏ khỏi tạp chí. Điều này làm tăng yêu cầu I / O cho hoạt động viết chuyên sâu.

Bạn có thể muốn sử dụng một hệ thống tập tin mà không có nhật ký cho bộ đệm.

Thay vì ionice, bạn có thể sử dụng lệnh ngủ để đánh giá giới hạn các hành động. Điều này sẽ hoạt động ngay cả khi ionice không, nhưng sẽ mất nhiều thời gian để xóa tất cả các tệp của bạn.


2

Tôi đã nhận được nhiều câu trả lời / nhận xét hữu ích ở đây, mà tôi muốn kết luận cũng như trình bày giải pháp của mình.

  1. Có, cách tốt nhất để ngăn chặn điều đó xảy ra là giữ bộ đệm cache trên một hệ thống tập tin riêng biệt. Nuking / định dạng nhanh một hệ thống tệp luôn mất tối đa vài giây (có thể là vài phút), không liên quan đến số lượng tệp / thư mục có mặt trên đó.

  2. Các ionice/ nicegiải pháp đã không làm gì cả, vì quá trình xóa thực sự gây ra hầu như không có I / O. Điều gây ra I / O là tôi tin rằng hàng đợi / bộ đệm ở cấp độ hệ thống tập tin / nhân được lấp đầy khi các tệp bị xóa quá nhanh bởi quá trình xóa.

  3. Cách tôi giải quyết nó tương tự như giải pháp của Tero Kilkanen, nhưng không yêu cầu gọi một kịch bản shell. Tôi đã sử dụng --bwlimitchuyển đổi tích hợp của rsync để hạn chế tốc độ xóa.

Lệnh đầy đủ là:

mkdir empty_dir
rsync -v -a --delete --bwlimit=1 empty_dir/ cache.bak/

Bây giờ bwlimit chỉ định băng thông tính bằng kilobyes, trong trường hợp này được áp dụng cho tên tệp hoặc đường dẫn của tệp. Bằng cách đặt nó thành 1 KBps, nó đã xóa khoảng 100.000 tệp mỗi giờ hoặc 27 tệp mỗi giây. Các tệp có đường dẫn tương đối như cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e, dài 47 ký tự, do đó, nó sẽ cung cấp 1000/47 ~ = 21 tệp mỗi giây, tương tự như dự đoán của tôi về 100.000 tệp mỗi giờ.

Bây giờ tại sao --bwlimit=1? Tôi đã thử các giá trị khác nhau:

  • 10000, 1000, 100 -> hệ thống chậm lại như trước
  • 10 -> hệ thống hoạt động khá tốt trong một thời gian, nhưng tạo ra sự chậm lại một phần mỗi phút hoặc lâu hơn. Thời gian phản hồi HTTP vẫn <1 giây.
  • 1 -> không có hệ thống chậm nào cả. Tôi không vội và 2 triệu tệp có thể bị xóa trong <1 ngày theo cách này, vì vậy tôi chọn nó.

Tôi thích sự đơn giản của phương thức tích hợp của rsync, nhưng giải pháp này phụ thuộc vào độ dài của đường dẫn tương đối. Không phải là một vấn đề lớn vì hầu hết mọi người sẽ tìm thấy giá trị phù hợp thông qua thử và sai.


Và bây giờ tôi tò mò không biết hiệu ứng đĩa sẽ như thế nào nếu bạn làm một cái gì đó như "mv cache.dir-old / dev / null"
ivanivan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.