/var/log가 가득 차서 서비스가 멈추는 사고는 거의 항상 로그가 회전되지 않아서 생깁니다. 애플리케이션은 로그를 계속 쌓는데 아무도 지우지 않으면 단일 파일이 수 GB까지 자랍니다. logrotate는 이걸 주기·크기 기준으로 자동 회전·압축·삭제해 주는 표준 도구입니다.
증상 — 어디서 새고 있나
먼저 어떤 로그 파일이 비대해졌는지 확인합니다.
du -h /var/log/* | sort -rh | head
ls -lh /var/log/nginx/access.log
단일 파일이 수백 MB 이상이면 회전 설정이 없거나 동작하지 않는 것입니다.
설정은 어디에 있나
logrotate는 두 곳을 읽습니다. 전역 기본값은 /etc/logrotate.conf, 서비스별 설정은 /etc/logrotate.d/ 아래에 패키지가 깔아둔 파일들입니다.
cat /etc/logrotate.conf
ls /etc/logrotate.d/
설정 문법
애플리케이션 로그용 설정 예시입니다. /etc/logrotate.d/myapp 에 저장합니다.
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myapp myapp
sharedscripts
postrotate
systemctl reload myapp >/dev/null 2>&1 || true
endscript
}
| 지시어 | 의미 |
|---|---|
daily / weekly | 회전 주기 |
rotate 14 | 14개까지 보관 후 가장 오래된 것 삭제 |
compress | 회전된 로그를 gzip 압축 |
delaycompress | 직전 회전본은 압축 보류(아직 쓰는 프로세스 대비) |
notifempty | 비어 있으면 회전 안 함 |
create | 회전 후 새 빈 파일을 권한·소유자 지정해 생성 |
크기 기준이 필요하면 daily 대신 size 100M 또는 maxsize 100M을 씁니다.
검증 — 적용 전 반드시 dry-run
설정을 실제로 돌리기 전에 -d(debug, dry-run)로 무엇이 일어날지 확인합니다. 파일은 건드리지 않습니다.
logrotate -d /etc/logrotate.d/myapp
출력에서 rotating log ..., considering log ... 줄을 읽어 의도대로 회전 대상이 잡히는지 봅니다. 강제로 한 번 실행하려면 -f를 씁니다.
logrotate -f /etc/logrotate.d/myapp
copytruncate가 필요한 경우
기본 회전은 파일을 mv 한 뒤 새 파일을 만드는 방식이라, 프로세스가 원래 파일 디스크립터를 계속 잡고 있으면 새 파일에 안 쓰고 옛 파일(이름만 바뀐)에 계속 씁니다. 로그를 reopen하지 못하는 애플리케이션은 copytruncate로 원본을 복사 후 비우는 방식을 씁니다.
/var/log/legacy/app.log {
daily
rotate 7
compress
copytruncate
}
copytruncate는 복사와 truncate 사이 짧은 순간 로그 유실 가능성이 있으므로, reload로 reopen이 되는 앱은 postrotate를 먼저 고려합니다.
체크리스트
du -h /var/log/* | sort -rh | head # 비대한 로그 찾기
cat /etc/logrotate.d/<service> # 회전 설정 존재 확인
logrotate -d /etc/logrotate.d/<service> # dry-run으로 검증
logrotate -f /etc/logrotate.d/<service> # 강제 1회 실행
cat /var/lib/logrotate/status # 마지막 회전 시각 기록
/var/lib/logrotate/status에 각 로그의 마지막 회전 날짜가 기록되니, "왜 어제 안 돌았지?"를 추적할 때 여기를 봅니다.
logrotate로 디스크를 안정적으로 지키는 실습과 로그·디스크 운영 감각은 리눅스 트랙에서 회원가입 없이 무료로 익힐 수 있습니다.