[server] 서버를 방해하지 않고 수백만 개의 파일을 삭제하는 방법

nginx 캐시 디렉토리를 삭제하고 싶습니다.이 디렉토리는 빠르게 제거됩니다.

mv cache cache.bak
mkdir cache
service nginx restart

이제 cache.bak2 백만 개의 파일 이있는 폴더가 있습니다. 서버를 방해하지 않고 삭제하고 싶습니다.

간단한 rm -rf cache.bak것은 서버를 휴지통에 버리고, rm이 실행되는 동안 가장 간단한 HTTP 응답조차 16 초가 걸리므로 그렇게 할 수 없습니다.

나는 시도 ionice -c3 rm -rf cache.bak했지만 도움이되지 않았다. 서버에 SSD가 아닌 HDD가있을 수 있습니다. 아마도 SSD에는 문제가되지 않을 수 있습니다.

최고의 솔루션은 nginx의 내장 캐시 관리자와 같은 일종의 조절 기능이라고 생각합니다.

이 문제를 어떻게 해결 하시겠습니까? 정확히이 작업을 수행 할 수있는 도구가 있습니까?

우분투 16.04의 ext4



답변

다음과 같이 bash 스크립트를 만드십시오.

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

deleter.sh예를 들어 이름으로 저장하십시오 . 실행 가능 chmod u+x deleter.sh하도록 실행하십시오 .

이 스크립트는 전달 된 모든 파일을 인수로 삭제 한 다음 0.5 초 동안 대기합니다.

그런 다음 실행할 수 있습니다

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

이 명령은 cache.bak의 모든 파일 목록을 검색하고 한 번에 5 개의 파일 이름을 삭제 스크립트로 전달합니다.

따라서 한 번에 삭제되는 파일 수와 각 삭제 작업 사이의 지연 시간을 조정할 수 있습니다.


답변

주석에 언급 된대로 마운트 / 마운트 해제 할 수있는 별도의 파일 시스템에 캐시를 저장하는 것을 고려해야합니다. /usr/bin/find /path/to/files/ -type f -print0 -exec sleep 0.2 \; -exec echo \; -delete찾기 바이너리가 / usr / bin 아래에 있고 화면에서 진행률을보고 싶다고 가정 할 때까지이 하나의 라이너를 사용할 수 있습니다 . 그에 따라 수면을 조정하여 HDD에 과도한 스트레스를주지 않도록하십시오.


답변

find 명령의 출력을 소비하는 스크립트에서 ionice를 시도 할 수 있습니다. 다음과 같은 것 :

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
)

파일 시스템에 따라 각 파일을 삭제하면 해당 디렉토리 전체가 다시 작성 될 수 있습니다. 대히트 될 수있는 큰 디렉토리의 경우. inode 테이블에 추가 업데이트가 필요하며 여유 공간 목록이있을 수 있습니다.

파일 시스템에 저널이 있으면 변경 사항이 저널에 기록됩니다. 적용된; 저널에서 제거되었습니다. 이것은 쓰기 집약적 인 활동에 대한 I / O 요구 사항을 증가시킵니다.

캐시에 대한 저널없이 파일 시스템을 사용할 수 있습니다.

ionice 대신 sleep 명령을 사용하여 동작을 제한 할 수 있습니다. ionice가 작동하지 않더라도 작동하지만 모든 파일을 삭제하는 데 시간이 오래 걸립니다.


답변

여기에 많은 유용한 답변 / 의견이 있으며 결론을 내리고 솔루션을 보여주고 싶습니다.

  1. 그렇습니다. 이런 일이 발생 하지 않도록 하는 가장 좋은 방법 은 캐시 디렉토리를 별도의 파일 시스템에 유지하는 것입니다. 파일 시스템의 Nuking / 빠른 포맷은 파일 / 디어의 수와 관계없이 항상 몇 초 (몇 분)가 소요됩니다.

  2. ionice/의 nice삭제 프로세스가 실제로 거의 I / O 발생하기 때문에 솔루션은 아무 짓도하지 않았다. I / O의 원인은 삭제 프로세스에 의해 파일이 너무 빨리 삭제 될 때 커널 / 파일 시스템 레벨 큐 / 버퍼가 채워 진다고 생각했기 때문입니다.

  3. 내가 해결 한 방법은 Tero Kilkanen의 솔루션과 비슷하지만 쉘 스크립트를 호출 할 필요는 없습니다. rsync의 내장 --bwlimit스위치를 사용 하여 삭제 속도를 제한했습니다.

전체 명령은 다음과 같습니다.

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

bwlimit는 kilobyes 단위로 대역폭을 지정하며,이 경우 파일 이름 또는 파일 경로에 적용됩니다. 1KBps로 설정하면 시간당 약 100,000 개의 파일 또는 초당 27 개의 파일이 삭제되었습니다. 파일에는 cache.bak/e/c1/db98339573acc5c76bdac4a601f9ec1e47 자 길이의 상대 경로 가 있으므로 초당 1000/47 ~ = 21 파일을 제공하므로 시간당 100,000 파일을 추측하는 것과 비슷합니다.

--bwlimit=1? 나는 다양한 가치를 시도했다.

  • 10000, 1000, 100-> 이전과 같이 시스템 속도가 느려짐
  • 10-> 시스템은 한동안 꽤 잘 작동하지만 1 분에 한 번 정도 부분적으로 느려집니다. HTTP 응답 시간이 여전히 1 초 미만입니다.
  • 1-> 시스템 속도 저하가 전혀 없습니다. 나는 서두르지 않으며이 방법으로 2 백만 개의 파일을 <1 일 안에 삭제할 수 있으므로 선택합니다.

나는 rsync의 내장 메소드의 단순함을 좋아하지만이 솔루션은 상대 경로의 길이에 달려 있습니다. 대부분의 사람들이 시행 착오를 통해 올바른 가치를 발견 할 것이므로 큰 문제는 아닙니다.


답변