2013-05-23 4 views
1

목표는 dir에서 1 천만 개의 임시 파일을 삭제하는 것이 었습니다. 그래서, 이렇게하기 위해 파이썬 스크립트를 작성하려고했습니다.수백만 개의 파일을 삭제하는 동안 스크립트가 주기적으로 정지되는 이유는 무엇입니까?

#!/usr/bin/python 

import os,sys 
dirname = os.getcwd() if len(sys.argv) == 1 else sys.argv[1] 
deleteConfirm = raw_input('Delete all files from dir ' + str(dirname) + ' (y/n)? ') 
if(deleteConfirm not in ['y','Y']): 
    os._exit(0) 

counter = 0 
flist = os.listdir(dirname) 
for file in flist: 
    os.remove(os.path.join(dirname, file)) 
    counter+=1 
    if(0==counter%1000): 
     sys.stdout.write('\rDeleted %d files' % counter) 
     sys.stdout.flush() 

print '\nDeleted %d files' % counter 

이 코드는 작동하지만, 나는 그것이 모든 10~15초을 중지하고 분 정도 작동하지 않는 것으로 확인 : 첫 번째 시나리오는 that처럼 보였다. 예를 들어, 처음 몇 초 시나리오는 삭제 된 파일의 수를 빠르게 출력합니다. 단지 3 ~ 5 초 동안 28000 개의 파일을 삭제하지만 그 출력은 "Deleted 28000 files"에서 멈추고 오랜 시간 동안 기다립니다. 그런 다음 다시 신속하게 업데이트하고 몇 초 안에 수천 개의 파일을 삭제합니다. 그러나 또 다시 멈추고 뭔가 기다리고 있습니다. 나는 이것이 잠긴 파일 때문이라고 생각하기 때문에 python3과 다중 처리 모듈을 사용하여 몇 가지 프로세스에서 파일을 삭제하는 새로운 시나리오를 작성하려고했습니다. 어떤 파일이 언 클럭킹을 기다리는 경우에도 다른 프로세스가 작업을 수행하기 때문에 도움이 될 것이라고 생각했습니다.

Here는 새로운 스크립트입니다

#!/usr/bin/python3 

import os, sys, time 
from multiprocessing import Pool 
dirname = os.getcwd() if len(sys.argv) == 1 else sys.argv[1] 
procNum = 5 if len(sys.argv) < 3 else sys.argv[2] 
deleteConfirm = input('Delete all files from dir ' + str(dirname) + ' (y/n)? ') 
if(deleteConfirm not in ['y','Y']): 
    sys.exit() 

def main(): 
    flist = os.listdir(dirname) 
    count = len(flist) 
    if count < 100000: 
     counter = 0 
     for file in flist: 
       os.remove(os.path.join(dirname, file)) 
       counter+=1 
       if(0==counter%1000): 
        sys.stdout.write('\rDeleted %d files' % counter) 
        sys.stdout.flush() 
      print('\rDeleted %d files' % counter) 
      sys.exit(0) 
     else: 
      workers = Pool(processes=procNum)  
      result = workers.imap_unordered(delfile,flist) 
     workers.close() 
     while True: 
        time.sleep(5) 
        completed = result._index 
        if completed == count: 
         print('') 
         break 
        sys.stdout.write('\rRemoved %d files' % result._index) 
      workers.join() 

def delfile(fname): 
    os.remove(os.path.join(dirname,fname)) 

나는이 새로운 스크립트를했지만, 그것은 이전의 시나리오로, 몇 초마다 중지합니다. 알아낼 수 없는데, 왜 이런 일이 일어나고 있는지. 어떤 아이디어?

+6

디렉토리에 실제로 수백만 개의 파일이 있다면 파일 시스템에 문제가있을 수 있습니다. 파일 시스템 자체에 병목 현상이 발생할 가능성이 있습니다. – mgilson

+3

일반적인 사용 사례로 "1000 만 개의 파일 삭제"를 중심으로 설계된 OS는 거의 없습니다. 왜 그렇게 많은 파일을? 이 모든 파일은 단일 디렉토리에 있습니까? –

+0

@mgilson에 동의하면 Python이 아닌 Linux에서 문제가 발생할 가능성이 높습니다. 나는'os.remove '의 내부 동작이 어떻게 작동하는지 알지 못하지만 쉘 확장 블록을 치는 것과 관련이있을 수 있습니다. 이 명령을'os.remove' 대신에 쉘에 전달해보십시오.'find. -exec/bin/rm {} \;'(이것은 셸 확장 문제를 제거해야합니다) – Andenthal

답변

5

자세한 내용은 Linux 설명서를 참조하십시오. Linux를 사용하고 있다고 가정합니다 (다른 OS는 다를 수 있음). 예 : https://www.kernel.org/doc/Documentation/sysctl/vm.txt을 참조하십시오.

리눅스는 디스크에 물리적 복사본이 보류중인 메모리 섹션 인 "더티 페이지"를 생성하여 디스크에 쓰기를 처리합니다. 실제 사본은 나중에 제공됩니다. 그래서 os.remove()은 대개 매우 빠릅니다 : 메모리에서 페이지를 만들거나 수정하고 나중에 복사하기 위해 실제 사본을 남겨 두는 것입니다. (만약 우리가 같은 페이지의 메모리를 바꿀 필요가 있다면, 우리는이 페이지를 여러 번 디스크에 쓸 필요가 없다.)

일반적으로 "pdflush"라는 데몬은 주기적으로 깨어 난다. 이 작업을 디스크에 기록합니다. 그러나 프로세스가 많은 더티 페이지를 생성하면 커널은 어느 시점에서 (os.remove() 호출 중 무작위 중 하나를 멈추고) 보류중인 페이지의 일부분에 대해 디스크에 쓰기를 강제 실행합니다. 더티 페이지가 적당한 임계 값 이하로 떨어지면 프로그램을 계속 진행할 수 있습니다. 아마도 "pdflush"는 즉시 나머지 부분을 계속 작성합니다. 분명히 프로그램이 더티 페이지를 계속 생성하면 다시 상한값에 도달하고 다시 일시 중지됩니다.

이것은 프로세스의 일시 중지 원인입니다. 이것은 커널이 작동하는 방식의 부작용입니다. 그것을 무시할 수 있습니다. 물리적으로 항상 디스크가 사용 중입니다.

+0

설명 주셔서 대단히 감사합니다! –

관련 문제