본문 바로가기

복사금지 블로그 짜증나서 만든 개발문서

rm 했는데 디스크 용량이 안 줄어들 때 확인하는 순서

반응형

환경  Linux · unlink(2) / lsof / logrotate · 2026-08-02 공식 문서 확인

로그를 지웠는데 df 값이 그대로인 경우가 있습니다. 파일 이름은 사라졌지만 프로세스가 아직 그 파일을 열어 두고 있어서입니다. 공식 매뉴얼 기준으로 원인을 찾고 공간을 되찾는 순서를 정리했습니다.

이름을 지운 것과 파일을 지운 것은 다르다

리눅스 unlink(2) 문서는 이 동작을 명확히 적어 두었습니다. 지우려는 이름이 그 파일의 마지막 링크였고 그 파일을 열어 둔 프로세스가 하나도 없을 때에만, 파일이 삭제되고 그 파일이 쓰던 공간이 재사용 가능해진다고 되어 있습니다.

같은 문서는 반대 경우도 함께 적습니다. 마지막 링크였더라도 어떤 프로세스가 그 파일을 여전히 열어 두고 있다면, 그 파일을 가리키는 마지막 파일 디스크립터가 닫힐 때까지 파일은 계속 존재한다는 것입니다. rm 이 지우는 것은 디렉터리에 걸린 이름이고, 데이터 블록은 열어 둔 쪽이 손을 뗄 때까지 그대로 남습니다.

로그 파일은 이 조건에 정확히 걸립니다. 애플리케이션은 시작할 때 로그 파일을 열고 프로세스가 사는 동안 그 디스크립터를 계속 쥐고 있습니다. 그 상태에서 파일 이름만 지우면 디렉터리에서는 사라지지만 프로세스는 여전히 같은 파일에 계속 기록합니다. 용량은 줄지 않고 오히려 늘어납니다.

# 파일시스템이 보고하는 사용량
df -h /var

# 디렉터리를 훑어 더한 사용량
du -sh /var/log

# 두 값이 크게 어긋나면 이름 없이 열려 있는 파일을 의심한다

du 는 디렉터리에 이름이 걸린 파일만 더합니다. 이름이 지워진 파일은 du 에 잡히지 않지만 df 에는 그대로 반영되어, 두 값의 차이가 곧 단서가 됩니다.

rm 은 이름을 끊을 뿐이고, 공간은 마지막 디스크립터가 닫혀야 돌아옵니다.

누가 붙잡고 있는지 먼저 확인한다

lsof 문서는 이 상황을 찾는 옵션을 따로 두고 있습니다. +L 은 파일의 링크 수를 함께 표시하게 하고, +L 뒤에 숫자를 붙이면 링크 수가 그 숫자보다 작은 파일만 나열합니다. 문서는 +L1 형태의 지정이 이미 unlink 된 열린 파일을 선택한다고 명시합니다.

출력에서 볼 것은 세 가지입니다. 어떤 명령이 붙잡고 있는지(COMMAND), 그 프로세스 번호(PID), 그리고 크기입니다. 여기서 나온 크기의 합이 df 와 du 의 차이를 대체로 설명해 줍니다. 설명이 되면 원인을 제대로 짚은 것이고, 설명이 안 되면 다른 마운트나 다른 원인을 더 봐야 합니다.

이 단계를 건너뛰고 로그를 더 지우는 대응이 흔한데, 상황을 더 나쁘게 만듭니다. 아직 필요한 로그까지 사라지고 공간은 여전히 그대로여서, 원인을 확인할 근거만 줄어듭니다. 무엇이 파일을 쥐고 있는지 먼저 특정하는 편이 빠릅니다.

# 이미 지워졌지만 아직 열려 있는 파일만 골라 본다
sudo lsof +L1

# 특정 파일시스템으로 좁혀서 보기
sudo lsof +L1 /var

# 의심되는 프로세스가 연 파일 전체를 확인 (-p 는 PID 지정)
sudo lsof -p 2481

NLINK 열이 0 인 항목이 이름 없이 살아 있는 파일입니다. SIZE 열의 합을 df·du 차이와 맞춰 보면 원인을 특정할 수 있습니다.

무엇을 더 지울지 고민하기 전에, 이미 지운 것을 누가 쥐고 있는지부터 봅니다.

공간을 되찾는 방법은 디스크립터를 닫는 것뿐이다

원인이 열린 디스크립터라면 해법도 거기서 나옵니다. 그 프로세스가 파일을 닫으면 커널이 공간을 반환합니다. 가장 깔끔한 방법은 해당 데몬이 지원하는 로그 재오픈 신호를 보내는 것입니다. 많은 서버 프로그램이 SIGHUP 을 받으면 로그 파일을 닫고 다시 엽니다. 다만 이 동작은 프로그램마다 다르므로, 신호를 보내기 전에 그 프로그램 문서에서 확인해야 합니다.

재오픈 신호를 지원하지 않는다면 프로세스를 재시작하는 것이 확실합니다. 서비스 중단이 부담이라면 응급 조치로 파일 내용만 비우는 방법이 있습니다. /proc/PID/fd 는 프로세스가 연 파일마다 하나씩 항목이 있고 각 항목은 실제 파일을 가리키는 심볼릭 링크라고 proc 문서에 적혀 있습니다. 이 경로를 통해 같은 파일을 0바이트로 잘라내면 공간이 즉시 돌아옵니다.

이 방법에는 대가가 있습니다. 잘라낸 내용은 복구되지 않고, 프로그램이 파일 오프셋을 유지한 채 계속 쓰면 앞부분이 빈 공간으로 남는 파일이 생길 수 있습니다. 급한 불을 끄는 용도로만 쓰고, 정리가 끝나면 재시작이나 재오픈으로 상태를 되돌리는 편이 낫습니다.

# 1) 로그 재오픈을 지원하는 데몬이면 이것으로 끝난다
sudo kill -HUP 2481

# 2) 지원하지 않으면 재시작이 확실하다
sudo systemctl restart myapp

# 3) 재시작이 어려울 때의 응급 조치 — 열린 파일을 0바이트로 자른다
sudo lsof -p 2481 | grep deleted        # 몇 번 디스크립터인지 확인
sudo truncate -s 0 /proc/2481/fd/7      # 그 번호를 지정해 비운다

df -h /var                              # 공간이 돌아왔는지 확인

3번은 되돌릴 수 없는 조치입니다. 디스크립터 번호를 잘못 지정하면 아직 쓰고 있는 다른 파일을 비우게 되므로, lsof 출력에서 번호를 반드시 확인하고 실행합니다.

같은 일이 반복된다면 로테이션 설정을 본다

한 번 겪고 끝날 문제가 아니라 매번 반복된다면 대개 로그 로테이션 쪽입니다. logrotate 문서는 기본 방식에서 회전 직후, 그리고 postrotate 스크립트가 실행되기 전에 방금 회전된 로그와 같은 이름의 파일이 새로 만들어진다고 설명합니다. 즉 기존 파일은 이름이 바뀌고 새 파일이 그 자리에 생깁니다.

여기서 프로그램에 알려 주지 않으면 문제가 시작됩니다. 프로그램은 이름이 바뀐 옛 파일의 디스크립터를 계속 쥐고 그쪽에 기록합니다. 새로 만들어진 파일은 계속 비어 있고, 옛 파일은 이름이 정리된 뒤에도 사라지지 않습니다. 그래서 postrotate 로 신호를 보내 로그를 다시 열게 하는 절차가 필요합니다.

프로그램에 로그를 닫으라고 지시할 방법이 아예 없는 경우를 위해 copytruncate 옵션이 있습니다. 문서는 이 옵션이 옛 로그 파일을 옮기고 새 파일을 만드는 대신, 사본을 만든 뒤 원본 파일을 그 자리에서 0바이트로 자른다고 설명합니다. 같은 문서가 한계도 함께 적어 두었는데, 복사와 잘라내기 사이에 아주 짧은 시간이 있어 그 사이의 로그 일부가 유실될 수 있다는 점입니다. 신호를 보낼 수 있다면 postrotate 가 낫고, 그럴 수 없을 때 쓰는 대안으로 보는 편이 맞습니다.

# 권장: 회전 후 프로그램에 로그를 다시 열라고 알린다
/var/log/myapp/*.log {
    daily
    rotate 14
    missingok
    notifempty
    postrotate
        systemctl kill -s HUP myapp.service
    endscript
}

# 대안: 프로그램에 로그를 닫으라고 지시할 방법이 없을 때만
/var/log/legacy/*.log {
    daily
    rotate 7
    copytruncate
}

copytruncate 는 복사와 잘라내기 사이의 기록이 유실될 수 있습니다. 감사 로그처럼 누락이 곤란한 대상에는 postrotate 방식을 씁니다.

회전은 파일을 옮길 뿐입니다. 프로그램에게 다시 열라고 알려 주는 절차가 빠지면 같은 일이 반복됩니다.

조치 후 확인할 것

  • df 와 du 값이 다시 비슷해졌는지 확인합니다. 여전히 크게 벌어져 있으면 다른 프로세스가 남아 있는 것입니다.
  • sudo lsof +L1 을 다시 실행해 링크 수 0 인 큰 파일이 남지 않았는지 봅니다.
  • 재시작이나 재오픈 뒤 애플리케이션이 새 로그 파일에 실제로 기록하고 있는지 tail 로 확인합니다.
  • logrotate 설정에 postrotate 신호나 copytruncate 중 하나가 들어 있는지 점검합니다.
  • 응급으로 파일을 잘라냈다면, 정리가 끝난 뒤 정상 재시작으로 상태를 되돌렸는지 확인합니다.

확인한 문서

정리하면 순서는 단순합니다. df 와 du 를 맞춰 보고, lsof +L1 으로 누가 쥐고 있는지 찾고, 그 프로세스가 파일을 닫게 합니다. 로그를 더 지우는 것은 이 순서 어디에도 들어가지 않습니다.

반응형