이전에는 매우 컸던 작은 디렉토리에서 "ls"가 왜 그렇게 오래 걸리나요? 이 문제를 어떻게 해결하나요?

이전에는 매우 컸던 작은 디렉토리에서 "ls"가 왜 그렇게 오래 걸리나요? 이 문제를 어떻게 해결하나요?

저는 Arch Linux를 실행하고 있으며 ext4 파일 시스템을 사용하고 있습니다.

ls지금은 실제로 작지만 예전에는 매우 컸던 디렉토리에서 실행 하면 잠시 동안 정지됩니다. 하지만 다음에 실행하면 거의 즉각적으로 실행됩니다.

나는 이것을 시도한다:

strace ls

하지만 솔직히 출력을 디버깅하는 방법을 모르겠습니다. 100줄이 넘더라도 필요하다면 게시할 수 있습니다.

그리고 아니요, 별칭을 사용하지 않습니다.

$ type ls
ls is hashed (/usr/bin/ls)

$ df .
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/sda9      209460908 60427980 138323220  31% /home

답변1

한때 큰 디렉토리에는 여전히 많은 블록이 디렉토리 항목(=해당 디렉토리에 있는 파일 및 하위 디렉토리의 이름과 inode 번호)에 할당되어 있을 수 있지만, 이제 해당 블록의 대부분은 삭제된 것으로 표시됩니다.

새 디렉토리가 생성되면 디렉토리 항목에 최소한의 공간만 할당됩니다. 더 많은 파일이 추가되면 필요에 따라 디렉토리 항목을 보관하기 위해 새 블록이 할당됩니다. 그러나 파일이 삭제되면 ext4파일 시스템은 곧 다시 필요할 수 있다고 가정하여 지금 필요하지 않은 디렉터리 항목과 사용 가능한 디렉터리 메타데이터 블록을 병합하지 않습니다.

e2fsck -C0 -f -D /dev/sda9추가 디렉터리 메타데이터 블록을 확보하고 기존 디렉터리 항목을 더 작은 공간에 병합하려면 파일 시스템을 마운트 해제하고 해당 시스템의 디렉터리를 최적화하기 위해 실행해야 할 수도 있습니다 .

이는 /home파일 시스템이므로 모든 일반 사용자 계정이 로그아웃되었는지 확인한 다음 루트(보통 텍스트 콘솔)로 로컬로 로그인하여 이를 수행할 수 있습니다. umount /home이 상황에서 파일 시스템이 사용 중이라고 보고 되면 를 사용하여 fuser -m /dev/sda9마운트 해제를 방해하는 프로세스를 식별 할 수 있습니다 /home. 이전 사용자 세션의 남은 부분인 경우 직접 종료할 수 있지만 서비스에 속하는 경우 제어된 방식으로 중지할 수 있습니다.

이러한 유형의 주요 유지 관리를 수행하는 또 다른 일반적인 방법은 /home시스템을 단일 사용자/긴급 모드로 부팅하는 것입니다. 사용된 배포판에서는 systemd부팅 옵션이 systemd.unit=emergency.target그 역할을 해야 합니다.

다른 사람들이 언급했듯이 더 간단한 해결책이 있습니다.디렉토리의 타임스탬프가 보존되는지 여부는 중요하지 않습니다., 문제 디렉터리는 해당 디렉터리가 있는 파일 시스템의 루트가 아닙니다. "비대해진" 디렉터리 옆에 새 디렉터리를 만들고, 모든 파일을 새 디렉터리로 이동하고, 이전 디렉터리를 삭제하고, 새 디렉터리의 이름을 동일하게 변경합니다. 이름은 예전처럼요. 예를 들어 /directory/A문제가 있는 경우:

mkdir /directory/B
mv /directory/A/* /directory/B/      # regular files and sub-directories
mv /directory/A/.??* /directory/B/   # hidden files/dirs too
rmdir /directory/A
mv /directory/B /directory/A

물론 디렉터리가 어떤 서비스에서 사용되고 있다면 해당 서비스를 먼저 중지하는 것이 가장 좋습니다.

답변2

호기심에 이것을 재현해 봅시다:

$ mkdir test
$ cd test
$ time ls   # Check initial speed of ls
real    0m0,002s
$ stat .    # Check initial size of directory
  File: .
  Size: 4096        Blocks: 8          IO Block: 4096   directory
  ...
$ seq 1 1000000 | xargs touch    # Create lot of files
$ echo 3 | sudo tee /proc/sys/vm/drop_caches   # Clear cache
$ time ls > /dev/null
real    0m1.588s
$ stat .                        # Check size of directory when files are there
  File: .
  Size: 22925312    Blocks: 44776      IO Block: 4096   directory

좋아요, 이제 우리는 큰 디렉토리를 갖게 되었습니다. 이 파일을 삭제하고 어떤 일이 일어나는지 살펴보겠습니다.

$ ls | xargs rm   # To avoid too long argument list
$ echo 3 | sudo tee /proc/sys/vm/drop_caches
$ time ls > /dev/null
real    0m1.242s
$ stat .
 File: .
 Size: 22925312     Blocks: 44776      IO Block: 4096   directory

그렇습니다 ls. TelcoM의 답변에서도 지적했듯이 디렉토리의 할당 크기가 실제로 커서 속도가 느려집니다.

문제가 단일 디렉터리인 경우 제거나 루트 액세스가 필요하지 않은 더 간단한 솔루션이 있습니다.새 디렉터리를 만들고 나머지 파일을 그 디렉터리로 옮긴 다음 비대해진 파일을 삭제하면 됩니다.

관련 정보