LabHub

CPU·메모리 누수 판별 · I/O 와 그 밖 · 이론

디스크와 파일 디스크립터

LabHub 에서 이어서 보기

한 줄 요약

df 에 여유가 있는데 쓸 수 없으면 inode 가 떨어졌거나 지워진 파일을 누가 열고 있다. 둘 다 df -h 로는 안 보인다.

왜 이게 필요했나

디스크 관련 신고에서 가장 자주 나오는 두 가지가 이것이다.

inode 고갈. 파일 하나하나가 inode 를 하나씩 쓴다. 작은 파일이 수백만 개면 용량은 남아도 inode 가 먼저 떨어진다. df -i 로 봐야 보인다.

지워졌지만 열려 있는 파일. 로그 파일을 rm 했는데 프로세스가 아직 그 파일을 열고 있으면, 리눅스는 링크만 지우고 실제 블록은 반환하지 않는다. df 는 여전히 꽉 찼다고 하고 du 는 파일이 없다고 한다. 이 불일치가 결정적 단서다.

# du 와 df 가 다르면 이걸 본다ls -l /proc/*/fd 2>/dev/null | grep deleted

해결은 프로세스에게 파일을 다시 열게 하는 것이다(로그라면 logrotatecopytruncate 또는 데몬에 SIGHUP). 프로세스를 재시작해도 된다.

어떻게 동작하나

파일 디스크립터 누수는 서서히 죽는다.

ls /proc/<PID>/fd | wc -l              # 지금 몇 개 열었나cat /proc/<PID>/limits | grep 'open files'   # 한도

이 숫자가 시간에 따라 단조 증가하면 닫지 않는 코드가 있다. 한도에 닿는 순간 Too many open files 로 요청이 전부 실패한다. 한도를 올리는 것은 시간을 버는 것이지 고치는 것이 아니다.

흔한 착각

ulimit -n 이 무제한이면 안전하다는 착각. 컨테이너의 기본 RLIMIT_NOFILE 은 사실상 무제한(10억 대)인데, 오래된 데몬 중에는 시작할 때 그 숫자만큼 연결 테이블을 잡으려다 메모리를 다 쓰고 죽는 것이 있다. 무제한이 항상 좋은 것은 아니다.

실무에서 진짜 중요한 것

로그 로테이션 설정에서 createcopytruncate 의 차이가 여기에 걸린다.

어느 쪽도 공짜가 아니다. 애플리케이션이 SIGHUP 을 처리하면 create, 못 하면 copytruncate 를 쓰되 유실 가능성을 안다.