리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 40 / 50 · Part 4. 프로세스·서비스·리소스
실습 환경: Rocky Linux 9 (10.0.0.200) · du·df·lsof +L1 재현은 실습 환경 실제 출력
이전 글: 39. CPU · Memory 관리

1. 들어가며

Part 4의 마지막 글은 디스크다. 디스크 가득 참은 서버 장애 원인 중 가장 흔한 것 중 하나지만, 관제 관점에서는 더 심각한 의미가 있다.

/var가 가득 차면 로그가 기록되지 않는다. 인증 로그, 감사 로그, 웹 로그가 모두 /var/log 아래에 쌓이기 때문이다. 로그가 끊긴 시간 동안 일어난 일은 나중에 분석할 방법이 없다. 그래서 디스크 사용량은 가용성 지표이면서 동시에 보안 가시성 지표 다.

이번 글에서 답할 질문:

  • df와 du는 무엇이 다르고, 왜 결과가 다를 수 있는가?
  • 파일을 지웠는데 용량이 줄지 않는 이유는?
  • 용량이 남았는데 "No space left on device"가 나는 이유는?

2. 핵심 개념

2-1. df와 du

도구기준보여주는 것
df -h파일시스템 전체 (슈퍼블록 정보)파티션별 크기·사용·남은 용량·마운트 지점
df -i파일시스템의 inode전체·사용·남은 inode 개수
du -sh DIR디렉터리를 순회 하며 파일 크기 합산특정 디렉터리가 차지한 용량

df는 "전체적으로 얼마나 찼나", du는 "어디가 크냐"를 본다.

2-2. 블록과 inode (14편 복습)

파일은 inode(메타데이터) + 데이터 블록 으로 저장된다. 둘 다 개수가 정해져 있으므로 어느 쪽이든 다 떨어지면 새 파일을 만들 수 없다.

고갈 대상증상흔한 원인
블록df -h Use% 100%큰 로그, 백업, 코어 덤프
inodedf -h는 여유, df -i IUse% 100%세션·캐시·메일 큐 같은 작은 파일 대량

2-3. 삭제된 파일이 공간을 차지하는 이유

rm은 디렉터리에서 이름(하드 링크) 을 지울 뿐이다. 커널은 링크 수가 0이고, 동시에 그 파일을 연 프로세스가 없을 때 비로소 inode와 데이터 블록을 해제한다. 로그 파일을 쓰고 있는 데몬이 있는 상태에서 로그를 rm하면:

  • du: 디렉터리에 이름이 없으니 안 보인다.
  • df: 블록은 아직 해제되지 않았으니 사용량 그대로.

3. 동작 원리

df와 du가 다를 때 — 삭제됐지만 열려 있는 파일

실습 환경에서 200MB 파일을 연 채로 삭제해 재현한 실제 출력이다.

# 200MB 파일 생성 후, 백그라운드 프로세스가 열어 둠
$ dd if=/dev/zero of=/tmp/big.log bs=1M count=200
$ (exec 3</tmp/big.log; sleep 20) &

$ df -h /tmp          # rm 전
/dev/vda        252G   13G   30G  29% /
$ rm /tmp/big.log
$ df -h /tmp          # rm 후 — 줄지 않음
/dev/vda        252G   13G   30G  29% /

$ lsof -nP +L1        # 링크 수(NLINK) 0 인데 열린 파일
COMMAND PID USER FD   TYPE DEVICE  SIZE/OFF NLINK   NODE NAME
sleep   778 root  3r   REG  254,0 209715200     0 950303 /tmp/big.log (deleted)

$ kill %1             # 파일을 연 프로세스 종료
$ df -h /tmp
/dev/vda        252G   12G   30G  29% /     ← 이제 해제됨

NLINK 0 + (deleted)가 핵심이다. 실제 운영에서는 로그를 rm한 뒤 rsyslog·httpd 같은 데몬을 재시작하지 않아 같은 일이 생긴다. 그래서 로그는 rm이 아니라 logrotate 로 관리하고, 급하게 비워야 한다면 : > file(truncate)로 이름은 두고 내용만 비운다.

du로 "어디가 큰가"를 찾는 실제 예(테스트 디렉터리)다.

$ du -sh dlab/* | sort -rh
121M	dlab/logs
36M	dlab/app
68K	dlab/cache          ← 빈 파일 3000개: 용량은 거의 없지만 inode 3000개 사용

cache는 용량으로는 작지만 inode를 3000개 쓴다. 이런 디렉터리가 수백만 개로 불어나면 df -h는 여유가 있는데도 파일을 만들 수 없게 된다.


4. 실습

# 1) 파티션별 사용량과 inode
df -hT
df -i

# 2) 큰 디렉터리 찾기 (-x: 다른 파일시스템으로 넘어가지 않음)
sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head
sudo du -xh --max-depth=1 /var | sort -rh | head
sudo du -sh /var/log/* | sort -rh | head

# 3) 큰 파일 찾기 (22편)
sudo find / -xdev -type f -size +500M -exec ls -lh {} \; 2>/dev/null

# 4) inode 를 많이 쓰는 디렉터리
sudo find /var -xdev -type f | cut -d/ -f1-4 | sort | uniq -c | sort -rn | head

# 5) 삭제됐지만 열린 파일
sudo lsof -nP +L1
sudo lsof -nP +L1 | awk 'NR>1 {s+=$7} END {printf "%.1f MB\n", s/1024/1024}'

# 6) 삭제된 열린 파일 비우기 (프로세스 재시작이 어려울 때)
sudo ls -l /proc/<PID>/fd | grep deleted
sudo sh -c ': > /proc/<PID>/fd/<N>'

# 7) journal 용량
journalctl --disk-usage
sudo journalctl --vacuum-size=500M

# 8) logrotate 설정·수동 실행 테스트
cat /etc/logrotate.conf; ls /etc/logrotate.d/
sudo logrotate -d /etc/logrotate.d/httpd     # dry-run

5. 결과 분석

아래 이상 상황 출력은 형식 설명용 예시다.

① /var 가득 참

$ df -h /var
Filesystem           Size  Used Avail Use% Mounted on
/dev/mapper/rl-var    10G   10G     0 100% /var

$ sudo du -xh --max-depth=1 /var/log | sort -rh | head -3
8.9G  /var/log
7.2G  /var/log/httpd
1.1G  /var/log/audit

/var/log/httpd가 7.2GB다. ls -lh로 보면 access_log 하나가 수 GB라면, 짧은 시간에 대량 요청(스캐닝·DoS, 25편)이 있었거나 logrotate가 동작하지 않은 것이다.

② inode 고갈

$ df -h /var     →  Use% 41%
$ df -i /var     →  IUse% 100%
$ sudo find /var -xdev -type f | cut -d/ -f1-4 | sort | uniq -c | sort -rn | head -1
 4812331 /var/lib/php

PHP 세션 파일이 480만 개다. 세션 정리(gc)가 동작하지 않았거나, 대량의 자동화 요청이 세션을 계속 만든 경우다.


6. 보안 관점

상황보안 의미
/var 100%로그 기록 중단 → 분석 공백. auditd는 설정(disk_full_action)에 따라 기록 중지·시스템 정지
의도적 디스크 채우기공격자가 로그를 못 남기게 대용량 파일 생성 (T1499 / 방어 회피)
(deleted) 열린 파일공격자가 실행 후 지운 도구·로그. 프로세스가 살아 있으면 /proc/PID/fd/N, /proc/PID/exe에서 복구 가능 (29편)
큰 숨김 파일/tmp/.x/ 등에 수집한 데이터 압축본 → 유출 준비 (T1074 Data Staged)
로그 급증무차별 대입(49편), 웹 스캔(25편)의 부산물

auditd의 /etc/audit/auditd.conf에는 space_left_action, disk_full_action이 있다. 보안 등급이 높은 서버는 감사 로그를 못 쓰면 시스템을 멈추도록(halt) 설정하기도 한다. 가용성과 추적성 중 무엇을 우선할지 정책으로 정해야 한다.


7. SOC / 보안관제 활용

7-1. 디스크 점검 스냅샷

{
  df -hT; df -i
  sudo du -xh --max-depth=1 /var/log | sort -rh | head
  sudo lsof -nP +L1 2>/dev/null
  sudo find /tmp /var/tmp /dev/shm -xdev -type f -size +50M -ls 2>/dev/null
} > /root/evidence/disk_$(date +%Y%m%d_%H%M).txt

7-2. 분석 흐름

[Alert]   SIEM: 서버 A 로그 수신 02:40 이후 중단 / 모니터링: /var 100%
   ↓
[df/du]   /var/log/httpd/access_log 7GB, 02:10 이후 급증
   ↓
[원인]    access_log: 단일 IP 초당 수백 요청, 디렉터리 스캔 패턴 (25편)
   ↓
[lsof]    +L1 → 관리자가 rm 한 access_log.1 (deleted) 4GB → httpd reload 로 해제
   ↓
[공백]    02:40~03:10 로컬 로그 없음 → SIEM 에 먼저 전송된 로그와 방화벽 로그로 보완
   ↓
[Response] IP 차단, logrotate 크기 기준 추가, /var/log 별도 파티션·용량 경보

8. 핵심 정리

  • df는 파일시스템 전체, du는 디렉터리 순회 합계 다. df -i로 inode도 본다.
  • 공간은 블록 또는 inode 중 하나만 떨어져도 "No space left"가 된다.
  • rm해도 열린 파일은 해제되지 않는다 → lsof +L1로 찾고 프로세스 재시작 또는 truncate.
  • 로그는 rm이 아니라 logrotate, 급할 땐 : > file.
  • /var가 차면 로그 기록이 멈춘다 — 디스크는 보안 가시성 지표다.
  • (deleted) 열린 파일은 증거 복구 지점이기도 하다.

9. 다음 글

Part 4(프로세스·서비스·리소스)를 마쳤다. 프로세스가 어떻게 태어나고(31·35), 어떻게 관리되며(36~38), 어떤 자원을 쓰는지(33·39·40) 정리했다.

다음 글 「41. Linux 네트워크 구조」 부터 Part 5(네트워크·보안·SOC)가 시작된다. 애플리케이션의 데이터가 소켓 → 커널 TCP/IP 스택 → 네트워크 인터페이스를 거쳐 나가는 경로와, 그 경로 위에서 방화벽·로그·관제가 어디에 위치하는지를 먼저 그려 본다.


참고 자료

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글