공공부하자개발 · 영어 학습 노트
리눅스
리눅스 운영RHEL 에서 배포·운영하기0/13 완료
  • 01셸 기본과 파일 시스템
  • 02텍스트 처리 (grep·sed·awk)
  • 03프로세스·서비스 관리 (systemd)
  • 04자바 애플리케이션 배포
  • 05Tomcat·nginx 배포·재기동
  • 06로그·디스크 운영 (logrotate·cron)
  • 07네트워크 진단 (ss·curl·firewalld)
  • 08셸 스크립트 (운영 자동화)
  • 09장애 대응 (jstack·jmap·OOM killer·FD)
  • 10보안 기초 (ssh 강화·SELinux·감사 로그)
  • 11컨테이너 기초 (podman)
  • 12백업·복구 (설정·릴리스·DB 덤프)
  • 13Docker 실무
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 리눅스 운영 › 06 / 13

로그·디스크 운영 (logrotate·cron)

섹션 7진행 0 / 13
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

2. 핵심 원리

2.1 어디가 찼나: df 와 du

df 는 파티션 단위, du 는 폴더 단위입니다. df 로 어느 파티션이 찼는지 보고 du 로 그 안에서 범인을 좁힙니다.

bash
df -h                               # 파티션별 사용률, Use% 열
du -sh /var/log /opt/myapp/logs     # 폴더 합계
du -ah /opt/myapp/logs | sort -rh | head -n 10   # 큰 파일·폴더 상위 10

du -x 를 붙이면 다른 파티션으로 넘어가지 않아 / 에서 시작해도 빠릅니다. sort -rh 는 K·M·G 단위를 이해하고 내림차순 정렬합니다.

2.2 큰 파일·오래된 파일 찾기: find

find 의 -size 와 -mtime 이 정리의 핵심 조건입니다. 삭제 전에 반드시 -print 로 목록을 눈으로 봅니다.

조건 뜻
-size +100M 100MB 초과
-mtime +30 수정한 지 30일 넘음
-mtime -1 24시간 안에 수정
-name '*.log' 이름 패턴
! -name '*.gz' 패턴 제외

-mtime +30 은 "31일 이상" 입니다. 하루 단위로 내림하므로 경계가 하루 어긋날 수 있고, 정확한 시간이 필요하면 -mmin 을 씁니다.

2.3 삭제·압축·비우기

찾은 파일을 처리하는 세 가지 동작입니다. 어느 것을 쓸지는 파일이 지금 열려 있는지에 달렸습니다.

bash
find logs -name 'app.*.log' -mtime +30 -delete           # 삭제
find logs -name 'app.*.log' -mtime +7 ! -name '*.gz' -exec gzip {} \;   # 압축
: > logs/catalina.out                                    # 열린 파일 비우기

gzip 은 원본을 .gz 로 바꾸고 원본을 지웁니다. 압축된 로그는 zcat·zgrep 으로 풀지 않고 읽습니다. 02 레슨의 도구가 그대로 통합니다.

2.4 지웠는데 공간이 안 돌아온다

프로세스가 열고 있는 파일을 rm 하면 이름만 사라지고 데이터는 프로세스가 닫을 때까지 남습니다. df 는 그대로이고 du 로는 안 보이는 상태입니다.

bash
lsof +L1 | grep deleted             # 삭제됐지만 열린 파일 목록
lsof -p $(pgrep -f app.jar) | grep deleted
: > /proc/PID/fd/N                  # 그 파일을 비워 공간 회수

이래서 열린 로그는 rm 이 아니라 : > 파일 로 비웁니다. 자바 앱을 재시작하면 핸들이 닫혀 공간이 돌아오지만 그건 마지막 수단입니다.

2.5 logrotate 동작

logrotate 는 cron 이 매일 한 번 실행하는 프로그램으로 /etc/logrotate.d/ 의 설정을 읽어 로그를 백업합니다. "백업" 은 파일 이름을 바꾸고 새 파일을 만들고 오래된 것을 압축·삭제하는 것입니다.

지시어 뜻
daily weekly 백업 주기
rotate 14 14개 보관
maxsize 200M 주기 전이라도 크기 넘으면
compress gzip 압축
delaycompress 한 세대 뒤에 압축
dateext 이름에 날짜 붙임
missingok 파일 없어도 에러 안 냄
notifempty 빈 파일은 백업 안 함

기본 방식은 파일 이름을 바꾸는 것입니다. 이름이 바뀌어도 자바 프로세스는 옛 파일 핸들에 계속 쓰므로 새 파일이 비어 있는 문제가 생깁니다.

2.6 copytruncate

자바 앱의 stdout 이나 catalina.out 처럼 프로세스가 열고 있는 파일은 copytruncate 를 씁니다. 복사한 뒤 원본을 0 으로 비우므로 프로세스는 같은 파일에 계속 씁니다.

text
/opt/myapp/logs/stdout.log /opt/tomcat/logs/catalina.out {
    daily
    rotate 14
    maxsize 200M
    compress
    delaycompress
    copytruncate
    missingok
    notifempty
    dateext
    su myapp myapp
}

복사와 비우기 사이에 찍힌 몇 줄은 잃을 수 있지만 stdout 로그에서는 감수합니다. su myapp myapp 은 파일 소유자와 맞춰 권한 경고를 없앱니다.

2.7 logback 과 역할 분담

Spring Boot 의 logback 은 app.2026-09-10.log 처럼 날짜별로 스스로 백업합니다. 이 파일들은 logrotate 가 백업할 필요가 없고 오래된 것을 지우기만 하면 됩니다.

로그 백업(압축) 삭제
app.날짜.log logback logback maxHistory 또는 cron
stdout.log logrotate copytruncate logrotate rotate
catalina.out logrotate copytruncate logrotate rotate
.hprof 덤프 없음 cron find -delete

logback 의 maxHistory 와 totalSizeCap 을 설정하면 앱이 스스로 정리합니다. 다만 앱이 내려가 있는 동안은 동작하지 않으므로 cron 을 보조로 둡니다.

2.8 logrotate 검사와 강제 실행

설정을 만들면 dry run 으로 확인하고, 필요하면 즉시 한 번 백업해 봅니다.

bash
sudo logrotate -d /etc/logrotate.d/myapp     # dry run, 무엇을 할지만 출력
sudo logrotate -f /etc/logrotate.d/myapp     # 강제로 지금 한 번 백업
cat /var/lib/logrotate/logrotate.status      # 마지막 백업 시각 기록

-d 출력에 rotating pattern 과 log does not need rotating 이 보이면 설정이 읽힌 것입니다. 이 레슨은 실행 환경이 없어 파일 문법만 검토했고, 서버에서 -d 로 검사합니다.

2.9 cron 표현식

cron 은 다섯 칸으로 시각을 정합니다. 분, 시, 일, 월, 요일 순서입니다.

표현식 뜻
0 3 * * * 매일 03:00
*/10 * * * * 10분마다
0 9 * * 1-5 평일 09:00
30 1 1 * * 매월 1일 01:30
0 */6 * * * 6시간마다

요일은 0 과 7 이 일요일입니다. */N 은 N 간격, 1-5 는 범위, 1,15 는 나열입니다.

2.10 crontab 과 cron.d

사용자 단위 예약은 crontab -e, 시스템 단위는 /etc/cron.d/파일 입니다. cron.d 형식은 명령 앞에 실행 사용자 칸이 하나 더 있습니다.

bash
crontab -l                          # 내 예약 목록
crontab -e                          # 편집
sudo cat /etc/cron.d/myapp-cleanup  # 시스템 예약 파일

운영 서버는 cron.d 파일을 권장합니다. 배포 스크립트로 복사할 수 있고 git 에 남으며 어느 계정으로 도는지 파일에 적혀 있습니다.

2.11 cron 환경의 함정

cron 은 로그인 셸이 아니라 PATH 가 짧고 .bashrc 를 읽지 않습니다. 터미널에서 되던 명령이 cron 에서는 "command not found" 로 실패하는 이유입니다.

text
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""
10 3 * * *  myapp  find /opt/myapp/logs -name 'app.*.log*' -mtime +30 -delete >> /opt/myapp/logs/cleanup.log 2>&1

파일 위에 PATH 를 적고, 명령은 절대 경로를 쓰고, 출력을 파일로 남깁니다. MAILTO="" 는 출력을 메일로 보내려다 쌓이는 것을 막습니다. % 는 cron 에서 줄바꿈 뜻이라 date +\%F 처럼 이스케이프합니다.

2.12 inode 와 임시 파일

파일 수가 너무 많아도 디스크는 찹니다. df -h 는 여유가 있는데 파일을 못 만들면 inode 가 찬 것입니다.

bash
df -i                               # IUse% 열
find /tmp -type f -mtime +7 -delete # 오래된 임시 파일
find /opt/myapp/logs -type f | wc -l

자바 앱이 /tmp 에 작은 파일을 매 요청마다 만들고 안 지우면 몇 달 뒤 inode 가 찹니다. RHEL 은 systemd-tmpfiles 가 /tmp 를 10일 기준으로 정리하지만 앱 폴더는 직접 챙깁니다.

핵심 원리
  • 2.1 어디가 찼나: df 와 du
  • 2.2 큰 파일·오래된 파일 찾기: find
  • 2.3 삭제·압축·비우기
  • 2.4 지웠는데 공간이 안 돌아온다
  • 2.5 logrotate 동작
  • 2.6 copytruncate
  • 2.7 logback 과 역할 분담
  • 2.8 logrotate 검사와 강제 실행
  • 2.9 cron 표현식
  • 2.10 crontab 과 cron.d
  • 2.11 cron 환경의 함정
  • 2.12 inode 와 임시 파일
이전 섹션1 왜 배우는가2 / 7다음 섹션3 코드 예제