데이터베이스 쓰기가 실패하는데 디스크에 새로운 업무 파일이 생기지 않았다면, 반복해서 출력되는 오류 로그가 시스템 파티션을 먼저 가득 채웠을 가능성이 큽니다. 로그 용량 관리는 주기적으로 디렉터리를 삭제하는 작업이 아닙니다. 로그 기록, 순환, 보존을 각각 제어하고 실제로 공간이 회수되었는지 검증해야 합니다. 이 글에서는 Debian 12를 기준으로 시스템 저널과 단기 실행 작업의 파일 로그를 관리합니다. 데이터베이스 파일이나 기존 스토리지 구성은 변경하지 않습니다.
CloudSFP의 물리 서버에는 각각 직접 연결된 1TB NVMe 두 개가 기본으로 제공되며, 하드웨어 RAID는 없습니다. 두 디스크의 용량을 합쳐 로그가 저장되는 파일시스템의 여유 공간으로 간주해서는 안 됩니다. 로그 용량 한도는 실제 마운트 지점을 기준으로 정해야 합니다. 아래의 용량 설정은 모두 작업 예시이며, 서비스의 기본 설정이 아닙니다.
1. 먼저 사용량을 확인하고 디스크 블록과 inode를 구분하기
결제 후 콘솔에서 접속 정보를 확인하고 SSH로 로그인합니다. 서버에 주소가 여러 개 있으면 첫 번째 주소를 사용합니다. 먼저 상태를 변경하지 않는 점검 명령을 실행합니다.
df -hT / /var/log
df -i / /var/log
findmnt -T /var/log
sudo du -xhd1 /var/log
sudo journalctl --disk-usage
df는 파일시스템의 사용량을 보여 주고, du는 디렉터리에서 확인할 수 있는 파일의 사용량을 집계합니다. 두 결과가 반드시 같지는 않습니다. -x는 다른 파일시스템으로 넘어가지 않도록 하여 별도로 마운트된 볼륨의 사용량이 결과에 섞일 위험을 줄입니다. /var/log가 별도 파티션이 아니라면 시스템 파일과 함께 루트 파티션의 공간을 사용합니다.
공간은 충분하지만 inode가 거의 소진된 경우에는 가장 큰 로그만 찾을 것이 아니라 작은 파일이 대량으로 생성되는지 확인해야 합니다. 파일시스템, 사용 가능한 공간, inode 사용량, 가장 빠르게 증가하는 디렉터리를 기록한 뒤 처리 대상을 결정합니다. 이미 거의 가득 찬 파티션에 진단 기록을 계속 저장하지 마세요.
/var/log전체를 바로 삭제하거나, 아직 보존하지 않은 장애 로그를 잘라내지 마세요. 정리 전에 관련 시간대의 증거를 보존하고, 처리 대상이 데이터베이스 데이터, 트랜잭션 로그 또는 백업 파일이 아닌지 확인해야 합니다.
2. journald에 별도의 용량 한도 설정하기
영구 저장되는 저널은 일반적으로 /var/log/journal에 있습니다. 기본 설정 파일을 직접 덮어쓰는 것보다 drop-in 설정으로 제한을 관리하는 편이 변경 사항을 추적하고 되돌리기 쉽습니다. 다음 예시는 로그 용량 한도와 파일시스템에 남겨 둘 공간을 설정합니다.
sudo install -d -m 0755 /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/60-capacity.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=4G
MaxFileSec=1day
EOF
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
sudo journalctl --flush
sudo journalctl --disk-usage
sudo systemctl status systemd-journald --no-pager
SystemMaxUse는 저널이 사용할 용량 한도를 제어하고, SystemKeepFree는 같은 파일시스템에 일정 공간을 남겨 두도록 지정합니다. 실제 동작은 현재 남아 있는 용량의 영향도 받습니다. 이 설정들은 애플리케이션이 직접 기록하는 파일에는 적용되지 않습니다. MaxFileSec는 활성 파일 하나에 담을 수 있는 최대 시간 범위를 제어하며, 로그를 하루만 보존한다는 뜻은 아닙니다.
다른 프로그램이 같은 메시지를 텍스트 로그에도 기록한다면 저널 용량을 제한해도 그 복사본은 없어지지 않습니다. 로그가 전달되고 저장되는 경로를 확인하고 각각 관리해야 합니다. 확인 없이 시스템 로그 서비스를 비활성화하지 마세요.
정리 전에 순환시키고 결과 확인하기
sudo journalctl --rotate
sudo journalctl --vacuum-size=1G
sudo journalctl --disk-usage
df -h /var/log
vacuum은 보관 파일만 삭제하며 활성 파일을 직접 삭제하지 않습니다. 따라서 최종 사용량이 지정한 값과 정확히 일치한다고 보장할 수 없습니다. journald 재시작은 설정 변경 작업이므로 먼저 현재 서비스 상태를 확인해야 합니다. 실행 후에는 새로운 오류가 없는지, 업무 로그가 계속 저널에 기록되는지 점검합니다.
3. 파일 로그의 순환 주체를 명확히 정하기
먼저 어떤 프로그램이 로그를 기록하는지, 파일을 장시간 열린 상태로 유지하는지, 기존 규칙이 해당 경로를 이미 처리하는지 확인합니다. 같은 파일을 애플리케이션의 자체 순환 기능과 logrotate가 동시에 관리해서는 안 됩니다. 시스템의 기존 규칙과 중복되는 광범위한 경로 매칭 규칙도 추가하지 마세요.
점검 도구를 설치합니다.
sudo apt-get update
sudo apt-get install logrotate lsof
단기 실행 작업이 시작할 때마다 /var/log/local-batch/run.log를 다시 열고 종료할 때 파일을 닫는다고 가정하면, /etc/logrotate.d/local-batch에 다음 규칙을 작성할 수 있습니다.
/var/log/local-batch/run.log {
daily
maxsize 100M
rotate 7
compress
delaycompress
missingok
notifempty
create 0640
}
디렉터리와 원본 로그 파일은 미리 존재해야 하며, 소유권은 작업 실행 계정에 맞아야 합니다. create 0640에서 소유자를 지정하지 않으면 원본 파일의 소유자와 그룹을 그대로 사용합니다. 디렉터리에 비특권 계정의 쓰기를 허용한다면 su 지시어와 디렉터리 권한을 별도로 검토해야 하며, 이 규칙을 그대로 적용해서는 안 됩니다.
sudo logrotate -d /etc/logrotate.conf
systemctl list-timers --all --no-pager
-d는 시뮬레이션 결과만 출력하며 실제 순환은 수행하지 않습니다. 타이머나 cron의 실제 실행 주기를 확인하세요. maxsize는 logrotate가 호출될 때만 검사되므로 실시간으로 강제되는 상한이 아닙니다. rotate 7은 보관 파일을 7개 유지한다는 뜻이며, 반드시 7일간 보존한다는 의미는 아닙니다.
상시 실행 프로세스에는 애플리케이션이 지원하는 로그 파일 다시 열기 기능이 필요합니다. 파일 이름이 바뀐 뒤에도 프로세스가 기존 파일에 계속 기록할 수 있습니다. 사용할 신호를 추측하거나 copytruncate를 기본 선택으로 삼지 마세요. copytruncate는 복사와 잘라내기 사이에 로그가 유실될 수 있는 구간이 있습니다.
4. 격리된 디렉터리에서 순환과 권한 테스트하기
새 규칙을 테스트하기 위해 전역 설정에 강제 순환을 실행하지 마세요. 다음 테스트는 별도의 디렉터리와 상태 파일을 사용하므로 운영 로그에 영향을 주지 않습니다.
umask 077
test_dir=$(mktemp -d)
printf '%0200d\n' $(seq 1 20) >"$test_dir/run.log"
cat >"$test_dir/rules" <<EOF
"$test_dir/run.log" {
size 1k
rotate 2
create 0640
}
EOF
logrotate -d -s "$test_dir/state" "$test_dir/rules"
logrotate -s "$test_dir/state" "$test_dir/rules"
ls -l "$test_dir"
printf 'after rotation\n' >>"$test_dir/run.log"
cat "$test_dir/run.log"
보관 파일과 새로 생성된 활성 파일이 나타나고, 권한이 의도한 대로 설정되어 있어야 합니다. 마지막 쓰기 명령은 경로를 다시 열어 기록할 수 있다는 사실만 확인합니다. 상시 실행 애플리케이션이 자동으로 새 파일로 전환한다는 것을 입증하지는 않습니다. 운영 환경의 검증에서는 실제 작업으로 식별 가능한 로그 한 건을 생성하고, 새 활성 파일에 기록되었는지 확인해야 합니다.
테스트 디렉터리는 결과를 살펴볼 수 있도록 남겨 두었다가 확인 후 삭제합니다. 운영 규칙은 계속 시스템의 기존 상태 파일로 관리해야 합니다. 수동 실행과 예약 작업이 동시에 실행되지 않도록 하고, 같은 로그를 두 개의 상태 파일로 장기간 관리하지 마세요.
5. 공간 회수 결과를 검증하고 반복 오류 해결하기
파일을 삭제했는데도 여유 공간이 늘지 않았다면, 먼저 프로세스가 여전히 열고 있는 파일을 확인합니다.
sudo lsof +L1
df -h /var/log
df -i /var/log
sudo du -xhd1 /var/log
lsof +L1은 링크 수가 1보다 작은 열린 파일을 나열합니다. 경로, 크기, 프로세스를 함께 살펴 판단해야 하며, 출력된 모든 파일을 로그로 간주해서는 안 됩니다. 대상을 확인한 뒤 애플리케이션 문서에 따라 로그 파일을 다시 열고, 필요한 경우 해당 서비스를 재시작한 다음 df로 재확인합니다. 정체를 알 수 없는 프로세스를 종료하거나 해당 프로세스의 파일 디스크립터에 쓰는 방식으로 공간을 강제로 회수하지 마세요.
검증 결과로 최소한 다음 네 가지를 남겨야 합니다. 새 기록이 활성 파일에 들어가는지, 보관 파일 수가 규칙에 맞는지, 해당 계정이 계속 기록할 수 있는지, 파일시스템의 여유 공간이 비정상적으로 계속 줄어들지 않는지 확인합니다. 오류 메시지가 여전히 대량으로 반복된다면 실패 시 재시도, 잘못된 요청, 디버그 출력 등 원인을 해결해야 합니다. 로그 순환은 장애 해결을 대신할 수 없습니다.
용량 한도만으로 일정 기간의 로그 이력을 보장할 수도 없습니다. 로그가 몰리는 시간대에는 증가 속도가 빨라져 같은 용량 한도에서도 오래된 기록이 더 일찍 삭제됩니다. 장기 보존이 필요한 증거는 전송, 접근 제어, 백업을 별도로 설계하고 실제로 읽을 수 있는지도 검증해야 합니다. 로컬 로그 순환은 로컬 저장 공간의 사용량을 제한하는 역할만 하며, 백업을 대신하지 않습니다.
자주 묻는 질문
journalctl vacuum으로 모든 로그를 즉시 지정 크기 이하로 줄일 수 있나요?
아닙니다. vacuum은 보관된 저널만 삭제하고 활성 파일은 직접 삭제하지 않습니다. journalctl --rotate 후 journalctl --vacuum-size=1G를 실행하고 journalctl --disk-usage와 df를 함께 확인합니다.
로그를 삭제했는데 df의 여유 공간이 늘지 않는 이유는 무엇인가요?
프로세스가 삭제된 파일을 계속 열어 두었을 수 있습니다. sudo lsof +L1로 크기와 프로세스를 확인한 뒤, 애플리케이션이 지원하는 로그 재열기 기능을 사용하거나 해당 서비스를 재시작합니다.