Bối cảnh: máy chủ vật lý, khoảng hai năm tuổi, các ổ đĩa SATA 7200-RPM được kết nối với thẻ RAID 3Ware, ext3 FS gắn noatime và dữ liệu = đã đặt hàng, không tải điên, kernel 2.6,18-92.1,22.el5, thời gian hoạt động 545 ngày . Thư mục không chứa bất kỳ thư mục con nào, chỉ có hàng triệu tệp nhỏ (~ 100 byte), với một số tệp lớn hơn (vài KB).
Chúng tôi có một máy chủ đã hoạt động một chút trong vài tháng qua, nhưng chúng tôi chỉ nhận thấy nó vào một ngày khác khi nó bắt đầu không thể ghi vào một thư mục do nó chứa quá nhiều tệp. Cụ thể, nó bắt đầu ném lỗi này trong / var / log / message:
ext3_dx_add_entry: Directory index full!
Đĩa trong câu hỏi có nhiều nút còn lại:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 60719104 3465660 57253444 6% /
Vì vậy, tôi đoán điều đó có nghĩa là chúng ta đạt đến giới hạn số lượng mục có thể có trong tệp thư mục. Không biết có bao nhiêu tệp sẽ có, nhưng nó không thể nhiều hơn, như bạn có thể thấy, hơn ba triệu hoặc hơn thế. Không phải vậy đâu, phiền bạn! Nhưng đó là phần một trong câu hỏi của tôi: chính xác giới hạn trên là gì? Có điều chỉnh được không? Trước khi tôi hét lên, tôi muốn điều chỉnh lại ; thư mục khổng lồ này gây ra tất cả các loại vấn đề.
Dù sao, chúng tôi đã theo dõi vấn đề trong mã đang tạo ra tất cả các tệp đó và chúng tôi đã sửa nó. Bây giờ tôi bị mắc kẹt với việc xóa thư mục.
Một vài lựa chọn ở đây:
rm -rf (dir)
Tôi đã thử điều này đầu tiên. Tôi đã từ bỏ và giết nó sau khi nó chạy được một ngày rưỡi mà không có tác động rõ rệt nào.
- hủy liên kết (2) trên thư mục: Chắc chắn đáng xem xét, nhưng câu hỏi đặt ra là liệu có thể xóa các tệp trong thư mục qua fsck nhanh hơn so với xóa qua liên kết (2). Đó là, bằng cách này hay cách khác, tôi đã phải đánh dấu các nút đó là không sử dụng. Tất nhiên, điều này giả định rằng tôi có thể nói với fsck không bỏ các mục vào các tệp trong / mất + tìm thấy; mặt khác, tôi vừa chuyển vấn đề của mình Ngoài tất cả các mối quan tâm khác, sau khi đọc về vấn đề này thêm một chút, hóa ra tôi có thể phải gọi một số chức năng FS nội bộ, vì không có biến thể unlink (2) nào tôi có thể tìm thấy sẽ cho phép tôi xóa hoàn toàn một thư mục với các mục trong đó. Pooh.
while [ true ]; do ls -Uf | head -n 10000 | xargs rm -f 2>/dev/null; done )
Đây thực sự là phiên bản rút gọn; cái thực sự tôi đang chạy, nó chỉ thêm một số báo cáo tiến trình và dừng sạch khi chúng tôi hết tệp để xóa, là:
xuất i = 0; thời gian (trong khi [đúng]; làm ls -Uf | đầu -n 3 | grep -qF '.png' || phá vỡ; ls -Uf | đầu -n 10000 | xargs rm -f 2> / dev / null; xuất i = $ (($ i + 10000)); tiếng vang "$ i ..."; làm xong )
Điều này dường như đang làm việc khá tốt. Khi tôi viết bài này, nó đã xóa 260.000 tệp trong ba mươi phút qua.
- Như đã đề cập ở trên, giới hạn mục nhập trên mỗi thư mục có thể điều chỉnh?
- Tại sao phải mất "7m9.561s / người dùng 0m0.001s / sys 0m0.001s" thực sự để xóa một tệp duy nhất là tệp đầu tiên trong danh sách được trả về
ls -U
và phải mất mười phút để xóa 10.000 mục đầu tiên với chỉ huy trong số 3, nhưng bây giờ nó đang di chuyển khá vui vẻ? Đối với vấn đề đó, nó đã xóa 260.000 trong khoảng ba mươi phút, nhưng giờ mất thêm mười lăm phút để xóa thêm 60.000. Tại sao sự thay đổi lớn về tốc độ? - Có cách nào tốt hơn để làm điều này không? Không lưu trữ hàng triệu tệp trong một thư mục; Tôi biết điều đó thật ngớ ngẩn, và nó sẽ không xảy ra trên đồng hồ của tôi. Giải quyết vấn đề và xem qua SF và SO cung cấp rất nhiều biến thể về
find
việc sẽ không nhanh hơn đáng kể so với cách tiếp cận của tôi vì một số lý do rõ ràng. Nhưng ý tưởng xóa-qua-fsck có chân nào không? Hay cái gì khác hoàn toàn? Tôi rất muốn nghe suy nghĩ ngoài luồng (hoặc bên trong hộp không nổi tiếng).
Đầu ra kịch bản cuối cùng!:
2970000...
2980000...
2990000...
3000000...
3010000...
real 253m59.331s
user 0m6.061s
sys 5m4.019s
Vì vậy, ba triệu tệp đã bị xóa trong hơn bốn giờ.
rm -rfv | pv -l >/dev/null
. pv nên có sẵn trong kho EPEL .