- Published on
logrotate 후 디스크가 안 줄 때 - 삭제 파일 점유 해결
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버에서 logrotate를 돌려 오래된 로그를 삭제했는데도 df -h의 사용량이 그대로인 경우가 있습니다. 이때 많은 분들이 “삭제가 안 됐나?”를 먼저 의심하지만, 리눅스 파일 시스템의 동작 원리를 알면 원인이 명확해집니다.
핵심은 파일을 삭제(unlink)해도, 해당 파일을 열고 있는 프로세스가 남아 있으면 디스크 블록이 즉시 반환되지 않는다는 점입니다. 즉, 파일은 디렉터리 엔트리에서 사라졌지만, 열린 파일 디스크립터가 참조하는 동안은 공간을 계속 점유합니다.
이 글에서는 logrotate 이후 디스크가 안 줄어드는 대표 원인(삭제된 파일 점유), 점유 프로세스 추적, 안전한 해제 방법, 그리고 재발 방지 설정까지 실전 관점으로 정리합니다.
증상: df는 그대로인데 du는 줄었다
전형적인 패턴은 다음과 같습니다.
du -sh /var/log는 확 줄었는데df -h는 여전히 90% 이상
이는 du가 “현재 디렉터리 트리에 보이는 파일”만 합산하기 때문입니다. 반면 df는 파일 시스템의 실제 사용 블록을 보여주므로, 삭제됐지만 열려 있는 파일이 있으면 df만 높게 남습니다.
간단한 확인 예시는 아래와 같습니다.
df -h /var
sudo du -sh /var/log
둘의 차이가 크면, “삭제된 파일 점유”를 가장 먼저 의심하세요.
원리: 삭제(unlink)와 열린 파일 디스크립터
리눅스에서 파일 삭제는 보통 다음의 의미입니다.
- 디렉터리 엔트리에서 파일 이름 제거(unlink)
- inode의 링크 카운트 감소
- 링크 카운트가 0이더라도, 열려 있는 FD가 있으면 inode와 데이터 블록은 유지
- 마지막 FD가 닫히는 순간 실제로 공간 반환
그래서 로그 파일을 지워도, 애플리케이션이 계속 그 파일에 쓰고 있거나 FD를 잡고 있으면 용량이 줄지 않습니다.
1단계: 삭제된 파일을 잡고 있는 프로세스 찾기(lsof)
가장 빠르고 정확한 방법은 lsof로 “deleted” 표시를 찾는 것입니다.
sudo lsof +L1 | head
+L1은 링크 수가 1 미만(즉, 링크가 0인 삭제 파일)을 의미합니다.- 출력에서
deleted가 보이면 거의 확정입니다.
특정 디렉터리(예: /var/log)에 한정해서 보려면:
sudo lsof +L1 /var/log
로그 파일을 많이 잡는 대표 주체는 nginx, apache2, java, node, python, rsyslogd, journald 등입니다.
용량이 큰 것부터 보고 싶다면
lsof 출력의 SIZE/OFF 컬럼을 기준으로 정렬하면 “누가 가장 큰 공간을 붙잡고 있는지”를 빠르게 파악할 수 있습니다.
sudo lsof +L1 | awk '{print $7, $2, $1, $9}' | sort -n | tail -20
환경에 따라 컬럼 위치가 다를 수 있으니, 먼저 sudo lsof +L1 | head -n 5로 헤더를 확인한 뒤 조정하세요.
2단계: /proc로 파일 디스크립터 직접 확인
lsof가 없거나 최소 환경(container, initramfs 등)이라면 /proc를 직접 볼 수 있습니다.
프로세스 PID를 알고 있을 때:
sudo ls -l /proc/1234/fd | head
여기서 심볼릭 링크가 다음처럼 보이면 삭제 파일을 잡고 있는 것입니다.
- 경로 끝에
(deleted)가 붙음
특정 PID가 잡고 있는 삭제 파일만 필터링:
sudo ls -l /proc/1234/fd | grep deleted || true
3단계: 안전하게 공간 반환하기(재시작, 로그 reopen)
삭제된 파일이 잡혀 있는 상태에서 공간을 회수하는 방법은 크게 3가지입니다.
방법 A: 프로세스 재시작(가장 확실)
서비스 재시작은 해당 프로세스의 FD를 전부 닫게 하므로 공간이 즉시 반환됩니다.
sudo systemctl restart nginx
sudo systemctl restart your-service
다만 운영 환경에서는 재시작이 곧 장애로 이어질 수 있으니, 아래의 “reopen 신호”를 먼저 고려하세요.
관련해서 서비스가 재시작 루프에 빠지는 상황까지 겹치면 원인 추적이 복잡해집니다. systemd 재시작 관련 이슈는 아래 글도 함께 참고하면 좋습니다.
방법 B: 로그 파일 reopen 시그널 보내기(무중단에 가까움)
많은 데몬은 로그 파일을 다시 열도록 신호를 받을 수 있습니다.
nginx:USR1(로그 reopen)haproxy: 보통 reload 흐름- 일부 데몬:
HUP
예시(nginx):
sudo kill -USR1 $(cat /run/nginx.pid)
이렇게 하면 nginx가 기존 FD를 닫고 새 로그 파일을 열면서, 삭제된 파일 점유가 풀립니다.
방법 C: copytruncate는 응급 처치지만 권장도는 낮음
logrotate 설정에서 copytruncate를 쓰면 프로세스를 재시작하지 않고도 로그를 “복사 후 잘라내기”로 처리합니다.
/var/log/nginx/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
copytruncate
}
하지만 copytruncate는 다음 문제가 있습니다.
- 복사와 truncate 사이에 로그가 쓰이면 일부 유실 가능
- 대용량 파일일수록 I/O 부담이 큼
가능하면 애플리케이션이 지원하는 reopen 시그널 또는 정상적인 rotate 방식(아래 postrotate)을 권장합니다.
4단계: logrotate 설정을 올바르게(nginx 예시)
가장 흔한 정석은 postrotate에서 로그 reopen을 호출하는 방식입니다.
/var/log/nginx/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
[ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
포인트:
sharedscripts: 여러 파일 매칭 시postrotate를 한 번만 실행kill -USR1: nginx에 “새 로그로 갈아타라”는 신호
이 설정이 없으면, 로그 파일이 rename되거나 삭제되어도 nginx는 기존 FD에 계속 쓰고, 그 FD가 삭제 파일을 점유하는 문제가 발생합니다.
5단계: journald가 원인인 경우(로그rotate가 아니라 저널)
/var/log가 아니라 journal이 용량을 많이 먹는 경우도 많습니다. 이때는 logrotate가 아니라 journald 정책을 봐야 합니다.
현재 디스크 사용량:
journalctl --disk-usage
용량 제한(예: 1GB)으로 정리:
sudo journalctl --vacuum-size=1G
기간 기준 정리:
sudo journalctl --vacuum-time=7d
지속적으로 제한하려면 /etc/systemd/journald.conf에서 SystemMaxUse 등을 설정합니다.
6단계: 컨테이너 환경에서 더 자주 터지는 이유
쿠버네티스나 도커 환경에서는 다음 조합으로 문제가 자주 발생합니다.
- 애플리케이션이 파일로 직접 로그를 씀
- 사이드카/에이전트가 rotate 또는 삭제를 수행
- 프로세스는 FD를 계속 잡고 있음
또한 노드 디스크가 꽉 차면 파드가 CrashLoopBackOff로 번지거나, 로그 자체가 안 남는 상황이 생길 수 있습니다. 운영에서 증상이 겹친다면 아래 글도 함께 보면 문제 범위를 좁히는 데 도움이 됩니다.
7단계: 실전 트러블슈팅 체크리스트
1) df vs du 불일치 확인
df -h
sudo du -sh /var/log
2) 삭제 파일 점유 프로세스 찾기
sudo lsof +L1 | grep deleted | head -50
3) 가장 큰 점유 파일 확인
sudo lsof +L1 | grep deleted | sort -k7 -n | tail -20
환경에 따라 정렬 키는 조정이 필요합니다.
4) 무중단에 가까운 조치부터
- 지원 시: reopen 시그널(
USR1또는HUP) - 불가 시: 서비스 재시작
5) 재발 방지
logrotate에postrotate로 reopen 추가- 애플리케이션 로그를 stdout/stderr로 전환(컨테이너 권장)
journald용량 상한 설정
자주 하는 실수와 주의점
rm로 지웠는데 왜 계속 차 있나?
rm은 “이름을 지우는 것”에 가깝습니다. 프로세스가 열어 둔 FD가 살아 있으면 공간은 남습니다.
삭제된 파일을 truncate -s 0으로 줄이면 되나?
이미 삭제된 파일은 경로로 접근이 어렵습니다. /proc/PID/fd/FD번호로 접근해 truncate하는 트릭이 있지만, 운영에서는 실수 위험이 큽니다. 일반적으로는 reopen 또는 재시작이 더 안전합니다.
디스크가 꽉 차서 서비스가 불안정해졌다면
디스크 부족은 네트워크/애플리케이션 오류로도 번질 수 있습니다. 예를 들어 ALB 502·504 같은 현상으로 관측되기도 하니, 장애 타임라인에서 “디스크 이슈가 선행했는지”를 함께 확인하세요.
마무리
logrotate 후 디스크가 안 줄어드는 문제는 대부분 “삭제된 파일을 프로세스가 계속 열고 있는 상태”로 설명됩니다. 해결의 핵심은 두 가지입니다.
lsof +L1또는/proc/PID/fd로 점유 주체를 정확히 찾기- 재시작 대신 가능하면 로그 reopen 시그널을 사용하고,
logrotate에postrotate를 구성해 재발 방지하기
이 흐름대로 점검하면, 불필요한 파일 복구/대량 삭제 없이도 빠르게 디스크를 회수할 수 있습니다.