서버에서 로그 파일을 관리하지 않으면 디스크가 꽉 차 서버가 다운될 수 있습니다. logrotate는 로그 파일을 자동으로 회전(rotate)시키고 오래된 것은 삭제해주는 필수 도구입니다.

logrotate 동작 원리

오늘: app.log (현재 로그)
      ↓ 자동 처리
app.log.1    (어제 로그)
app.log.2.gz (그제 로그, 압축)
app.log.3.gz
...
app.log.7.gz (7일 전 로그)
[삭제]       (8일 이상 된 것)

설정 파일 위치

/etc/logrotate.conf         # 전역 기본 설정
/etc/logrotate.d/           # 서비스별 설정 디렉터리
/etc/logrotate.d/nginx      # Nginx 로그 설정 (패키지가 자동 생성)
/etc/logrotate.d/mysql      # MySQL 로그 설정

기본 설정 파일 구조

/var/log/myapp/*.log {
    daily           # 회전 주기 (daily/weekly/monthly/yearly)
    rotate 7        # 7개 파일 보존 (7일치)
    compress        # 회전된 파일 gzip 압축
    delaycompress   # 최신 회전 파일은 압축 보류 (다음 번에 압축)
    missingok       # 파일 없어도 오류 없이 넘어감
    notifempty      # 빈 파일은 회전하지 않음
    create 644 www-data www-data  # 새 로그 파일 생성 (권한 소유자 그룹)
    sharedscripts   # postrotate 스크립트를 한 번만 실행
    postrotate
        # 로그 회전 후 실행할 명령 (서비스에 새 파일 사용 신호)
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

Nginx 로그 설정 (기본 제공)

# 기존 설정 확인
cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    missingok
    rotate 52       # 52일(약 7주)치 보존
    compress
    delaycompress
    notifempty
    create 640 nginx adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}

MySQL 로그 설정

# /etc/logrotate.d/mysql
/var/log/mysql/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 640 mysql adm
    sharedscripts
    postrotate
        test -x /usr/bin/mysqladmin || exit 0
        if [ -f /var/run/mysqld/mysqld.pid ]; then
            mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs
        fi
    endscript
}

사용자 정의 애플리케이션 로그

# /etc/logrotate.d/myapp
/var/log/myapp/app.log
/var/log/myapp/error.log {
    daily
    rotate 30           # 30일치 보존
    size 100M           # 100MB 초과 시 즉시 회전 (daily와 OR 조건)
    compress
    delaycompress
    missingok
    notifempty
    copytruncate        # 파일을 복사 후 원본을 비움 (재시작 없이 로테이션)
                        # 주의: 데이터 손실 가능성 있음, postrotate 선호
    create 644 appuser appgroup
}

copytruncate vs postrotate

copytruncate:
  - 파일을 복사하고 원본을 0바이트로 만듦
  - 애플리케이션 재시작/신호 없이 작동
  - 복사~트런케이트 사이 짧은 시간 동안 로그 손실 가능

postrotate + kill -USR1:
  - 파일 이름을 변경하고 새 파일 생성
  - 애플리케이션에 새 파일 열도록 신호 전송
  - 더 안전하고 권장됨 (Nginx, Apache 등 지원)

수동 실행 및 디버깅

# 특정 설정 파일 테스트 (실제 실행 없이)
sudo logrotate -d /etc/logrotate.d/myapp

# 강제 실행 (이미 오늘 실행했더라도)
sudo logrotate -f /etc/logrotate.d/myapp

# 전체 logrotate 강제 실행
sudo logrotate -f /etc/logrotate.conf

# 상세 출력으로 실행
sudo logrotate -v /etc/logrotate.d/myapp

logrotate 실행 확인

# logrotate 상태 파일 (마지막 실행 날짜 기록)
cat /var/lib/logrotate/status | grep myapp

# 시스템 logrotate 타이머 확인
sudo systemctl status logrotate.timer
sudo systemctl list-timers | grep logrotate

# 실행 로그 확인
sudo grep logrotate /var/log/syslog | tail -10

로그 보존 용량 계산

# 예상 디스크 사용량 계산
# 일일 로그 크기 * 보존 일수

# 현재 로그 파일 크기
du -sh /var/log/nginx/
du -sh /var/log/mysql/

# 압축 효율 확인 (텍스트 로그는 보통 5~10배 압축)
ls -lh /var/log/nginx/*.gz

로그 없는 정적 파일 요청 제외

Nginx 설정에서 정적 파일 접근 로그를 꺼두면 로그 크기를 크게 줄일 수 있습니다:

location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 1y;
    access_log off;  # 정적 파일 접근 로그 비활성화
}

logrotate를 올바르게 설정하면 디스크 부족으로 인한 갑작스러운 서버 장애를 예방할 수 있습니다. 새 서비스를 설치할 때마다 해당 서비스의 로그 파일에 대한 logrotate 설정을 추가하는 습관을 들이세요.