Huny's Dev Blog
huny.dev

Linux 로그를 삭제했는데 디스크가 그대로라면: 열린 파일과 lsof +L1

Linux에서 삭제한 로그를 프로세스가 계속 열어 두는 상황을 Python으로 재현한다. unlink·close의 차이, df·du 관찰 범위, lsof +L1 점검과 로그 재열기 원칙을 정리한다.

Hun Jang
Hun Jang Oct 29, 2026

큰 로그 파일을 삭제했는데도 Linux 서버의 디스크 여유 공간이 늘지 않는다면, 프로세스가 삭제된 파일을 아직 열어 두고 있는지 먼저 확인할 필요가 있다. 파일 이름을 없애는 unlink와 열린 파일 참조를 닫는 close는 별개의 동작이다. 이 글에서는 임시 파일로 현상을 재현하고, lsof +L1로 원인을 좁히는 방법과 로그를 다시 열어야 하는 이유를 설명한다.

이름표가 떨어져도 실행 중인 프로세스와 연결된 파일을 표현한 개념 일러스트. 실제 파일시스템 구조도는 아니다.

파일 이름을 지워도 열린 파일은 남을 수 있다

Linux에서 unlink()는 디렉터리의 파일 이름을 제거한다. 마지막 이름을 지웠더라도 프로세스가 해당 파일을 열고 있으면 파일은 마지막 열린 디스크립터가 닫힐 때까지 유지된다. 반대로 다른 하드 링크가 남아 있다면 그 이름도 고려해야 한다. unlink(2)

로그를 기록하던 프로세스는 삭제된 이름을 매번 다시 찾는 대신 기존 파일 디스크립터로 계속 접근할 수 있다. 따라서 같은 경로에 빈 파일을 새로 만드는 것만으로 기존 로그 기록 대상이 바뀐다고 가정하면 안 된다.

df와 du가 보여주는 대상을 구분한다

df는 지정한 경로가 있는 파일시스템의 공간 사용량을 보여주고, du는 지정한 파일·디렉터리 아래의 사용량을 계산한다. 디렉터리에서 사라진 파일을 프로세스가 계속 열어 두고 있으면 두 관찰 결과가 다르게 보일 수 있다. df(1), du(1)

다음은 운영 환경에서 사용할 수 있는 점검 명령의 예다. 비교할 경로와 파일시스템 범위를 맞추고, 접근 권한 때문에 빠진 항목이 없는지도 확인한다. 두 수치의 차이만으로 삭제된 열린 파일이 원인이라고 단정하지 않는다.

Python으로 삭제 후에도 읽을 수 있는 파일 재현하기

아래 코드를 deleted_log_demo.py로 저장해 Linux에서 실행한다. 이 프로그램이 만든 임시 디렉터리의 파일만 삭제하며 기존 서버 로그는 건드리지 않는다. /proc/self/fd를 사용하므로 Linux의 procfs가 필요하다.

실제로 확인한 출력은 다음과 같다.

경로는 없어졌고 하드 링크 수는 0이지만, 열린 디스크립터로 조회한 논리 크기는 1 MiB이며 내용도 읽을 수 있다. 이때 st_size는 논리적인 파일 크기이지 회수될 디스크 블록 수의 측정값은 아니다. os.fstat()은 경로 대신 열린 디스크립터에 대한 정보를 읽는다. Python os.fstat 문서

/proc/PID/fd에는 프로세스가 열고 있는 디스크립터별 항목이 있다. 예제에서는 자신의 항목이 가리키는 경로에 (deleted) 표시가 붙는 것을 확인했다. 마지막 with 블록이 끝난 뒤에는 해당 디스크립터 번호에 접근하면 EBADF가 발생하는지도 검사한다. proc_pid_fd(5)

lsof +L1로 어떤 프로세스가 잡고 있는지 확인한다

lsof가 설치돼 있고 필요한 조회 권한이 있다면 다음 명령으로 링크 수가 1보다 작은 열린 파일을 찾을 수 있다. +L1은 이름이 제거된 열린 파일을 선택하는 옵션이다. lsof(8)

출력에서 프로세스 이름, PID, FD, 파일 종류, 디바이스·inode, 이름을 함께 확인한다. 정규 로그 파일을 찾는 상황이라면 REG 항목을 우선 살펴본다. 같은 파일을 여러 FD나 프로세스가 잡고 있을 수 있으므로 행별 크기를 단순 합산하지 않는다. SIZE/OFF도 파일 종류와 옵션에 따라 크기 또는 오프셋을 나타내므로 헤더와 의미를 확인한다.

이 명령은 문서를 기준으로 제시한 운영 점검 예다. 이번 검증에서는 사용자의 운영 서버를 조회하거나 프로세스를 재시작하지 않았다.

해결은 추가 삭제보다 로그 참조 정리다

원인을 확인한 뒤에는 서비스가 지원하는 로그 재열기나 로그 로테이션 절차를 우선 사용한다. 재시작이 필요하다면 서비스 영향과 복구 절차를 확인한 뒤 정상적으로 수행한다. 특정 신호를 보내면 모든 프로그램이 로그를 다시 연다고 가정하지 않는다.

이후 삭제된 파일을 잡고 있는 참조가 사라졌는지 다시 확인하고 파일시스템의 여유 공간을 재점검한다. 한 프로세스의 로그를 다시 열어도 다른 프로세스가 같은 파일을 잡고 있을 수 있다. 삭제를 반복하거나 디스크립터 경로를 임의로 잘라내는 것을 기본 복구 절차로 삼지 않는다.

검증 환경은 Python 3.12.14 / Linux x86_64다. 경로 소멸, 링크 수 0, 논리 크기 유지, 삭제 표시, 삭제 후 읽기, close 후 디스크립터 무효화의 6개 검증을 통과했다. 파일시스템 전체의 회수 블록 수, 실제 서비스의 로그 로테이션, 컨테이너·원격 파일시스템 동작은 검증하지 않았다.

참고 문서

English version

Linux Deleted Logs Still Use Disk Space: Open Files and lsof +L1Linux Deleted Logs Still Use Disk Space: Open Files and lsof +L1

추천 글