728x90
※ Linux: Disk I/O analysis script .
안녕하세요. 듀스트림입니다.
시스템을 운영하다 보면 Disk I/O를 체크해야 될 때가 있습니다.
물론 모니터링에서 찍어주지만, 조금 더 실시간성으로 정밀하게 분석해야 될 때 사용하시면 됩니다.
분석 Shell-scripts
아래 스크립트는 /proc/diskstats를 두 번 읽고, 각 디바이스에 대해 r/s, w/s, rkB/s, wkB/s, r_await, w_await, util%, avgqu를 계산하는 스크립트입니다.
#!/usr/bin/env bash
set -u
INTERVAL="${1:-1}"
DEVICE_REGEX="${2:-^(sd[a-z]+|vd[a-z]+|xvd[a-z]+|nvme[0-9]+n[0-9]+|dm-[0-9]+)$}"
TMP1="$(mktemp)"
TMP2="$(mktemp)"
trap 'rm -f "$TMP1" "$TMP2"' EXIT
read_stats() {
awk -v regex="$DEVICE_REGEX" '
$3 ~ regex {
printf "%s %s %s %s %s %s %s %s %s\n",
$3, $4, $6, $7, $8, $10, $11, $13, $14
}
' /proc/diskstats | sort
}
read_stats > "$TMP1"
sleep "$INTERVAL"
read_stats > "$TMP2"
awk -v interval="$INTERVAL" '
BEGIN {
printf "\n%-10s %8s %8s %10s %10s %10s %10s %8s %8s %-10s %s\n",
"DEVICE", "r/s", "w/s", "rkB/s", "wkB/s",
"r_await", "w_await", "util%", "avgqu", "STATE", "COMMENT"
printf "%s\n", "-----------------------------------------------------------------------------------------------------------------------------"
}
FNR==NR {
r_ios[$1]=$2
r_sec[$1]=$3
r_ms[$1]=$4
w_ios[$1]=$5
w_sec[$1]=$6
w_ms[$1]=$7
io_ms[$1]=$8
wio_ms[$1]=$9
next
}
{
dev=$1
dr_ios=$2-r_ios[dev]
dr_sec=$3-r_sec[dev]
dr_ms=$4-r_ms[dev]
dw_ios=$5-w_ios[dev]
dw_sec=$6-w_sec[dev]
dw_ms=$7-w_ms[dev]
dio_ms=$8-io_ms[dev]
dwio_ms=$9-wio_ms[dev]
rps = dr_ios / interval
wps = dw_ios / interval
rkBps = (dr_sec * 512 / 1024) / interval
wkBps = (dw_sec * 512 / 1024) / interval
rawait = (dr_ios > 0) ? dr_ms / dr_ios : 0
wawait = (dw_ios > 0) ? dw_ms / dw_ios : 0
util = (dio_ms / (interval * 1000)) * 100
avgqu = dwio_ms / (interval * 1000)
state="OK"
comment="Normal"
if (util > 90 && (rawait > 20 || wawait > 20)) {
state="CRITICAL"
comment="Disk saturated + high latency"
}
else if (util > 80 && avgqu > 1) {
state="WARN"
comment="Queue buildup (I/O backlog)"
}
else if (rawait > 10 || wawait > 10) {
state="WARN"
comment="High latency"
}
else if (util < 30 && (rawait > 5 || wawait > 5)) {
state="WARN"
comment="Sporadic delay"
}
else if (rps == 0 && wps == 0) {
state="IDLE"
comment="No disk activity"
}
printf "%-10s %8.1f %8.1f %10.1f %10.1f %10.2f %10.2f %8.1f %8.2f %-10s %s\n",
dev, rps, wps, rkBps, wkBps, rawait, wawait, util, avgqu, state, comment
}
' "$TMP1" "$TMP2"
echo
echo "[자동 판단 기준]"
echo "- OK : 정상"
echo "- WARN : 지연 발생 또는 큐 적체"
echo "- CRITICAL : 디스크 포화 + latency 증가 (병목 확정)"
echo "- IDLE : I/O 없음"
echo
echo "[해석 가이드]"
echo "- util > 80% + avgqu 증가 → I/O 밀림"
echo "- await > 10ms → 스토리지 지연 시작"
echo "- await > 20ms → 병목 가능성 높음"
echo "- util 낮은데 await 높음 → checkpoint / burst I/O 의심"
echo
사용법은 ./disk_io_check.sh <n> 인터벌 초를 줘서 사용하시면 됩니다. (값 미부여시 기본 인터벌은 1s)
스크립트 출력 컬럼 해석표
| 컬럼 | 의미 | 계산 기준 | 해석 |
| DEVICE | 디스크 장치명 | /proc/diskstats의 $3 | sda, nvme0n1 같은 장치 이름. |
| r/s | 초당 읽기 요청 수 | Δreads completed / interval | 최근 구간 동안 초당 몇 건의 read 요청이 처리됐는지 의미. 높을수록 read IOPS가 많은 상태. |
| w/s | 초당 쓰기 요청 수 | Δwrites completed / interval | 최근 구간 동안 초당 몇 건의 write 요청이 처리됐는지 의미. 높을수록 write IOPS가 많은 상태. |
| rkB/s | 초당 읽기 처리량 | Δread sectors × 512 / 1024 / interval | 초당 몇 KB를 읽었는지 보여줌. |
| wkB/s | 초당 쓰기 처리량 | Δwrite sectors × 512 / 1024 / interval | 초당 몇 KB를 썼는지 보여줌. checkpoint, 배치 작업, flush 구간에서 높아질 수 있음. |
| r_await | 읽기 1건당 평균 지연 시간(ms) | Δread time / Δread requests | read 요청이 완료되기까지 평균 얼마나 걸렸는지 의미. 큐에서 대기한 시간과 실제 처리 시간이 포함. |
| w_await | 쓰기 1건당 평균 지연 시간(ms) | Δwrite time / Δwrite requests | write 요청이 완료되기까지 평균 얼마나 걸렸는지 의미. 특히 PostgreSQL에서는 WAL flush, checkpoint, VACUUM 영향으로 중요. |
| util% | 측정 구간 동안 디스크가 바빴던 비율 | Δtime spent doing I/Os / elapsed time × 100 | 디스크가 얼마나 바빴는지 보여줌. 높을수록 바쁜 상태지만 이것만으로 병목을 단정하면 안 되고 await, avgqu와 같이 봐야 함. |
| avgqu | 평균 큐 길이 유사 지표 | Δweighted I/O time / elapsed time | I/O 요청이 얼마나 쌓였는지 추정하는 값. 높아질수록 처리 대기열이 길어지는 경향을 의미. |
| STATE | 자동 판단 상태 | 스크립트 조건문 | OK, WARN, CRITICAL, IDLE 중 하나로 표시. 수치를 사람이 직접 해석하지 않아도 대략적인 상태를 바로 볼 수 있게 만든 값. |
| COMMENT | 상태에 대한 설명 | 스크립트 조건문 | 왜 해당 상태로 판단했는지 짧게 보여줌. (예: Normal, High latency, Disk saturated + high latency) |
STATE 컬럼 해석표
| STATE | 의미 | 판단 기준 | 해석 |
| OK | 정상 | 기본값 | 디스크가 바쁘더라도 지연이 크지 않고 큐 적체가 심하지 않은 상태. |
| WARN | 주의 | util > 80 && avgqu > 1 또는 await 증가 등 | 병목 전조이거나 지연이 발생하는 상태. (원인 확인 필요) |
| CRITICAL | 심각 | util > 90 && (r_await > 20 또는 w_await > 20) | 디스크가 거의 포화된 상태에서 지연도 커진 경우. (실제 병목일 가능성이 높음) |
| IDLE | 유휴 | r/s == 0 && w/s == 0 | 측정 구간 동안 디스크 I/O가 없었던 상태. |
COMMENT 컬럼 해석표
| COMMENT | 의미 | 해석 |
| Normal | 정상 | 특별한 지연이나 큐 적체 없이 처리 중. |
| Disk saturated + high latency | 디스크 포화 + 높은 지연 | 바쁘기도 하고 느리기도 한 상태. (실질적 병목 가능성 높음) |
| Queue buildup (I/O backlog) | 큐 적체 | 요청이 처리보다 빨리 들어오면서 대기열이 쌓이는 상태. |
| High latency | 높은 지연 | 처리량이 많지 않아도 요청 한 건당 시간이 길어진 상태. |
| Sporadic delay | 간헐적 지연 | 평균 사용률은 높지 않지만 순간적으로 지연이 튄 상태. (flush, burst I/O 등을 의심) |
| No disk activity | I/O 없음 | 측정 구간 동안 read/write가 없었던 상태. |
패턴 해석
| 패턴 | 의미 | 체크 사항 |
| util% 높음, await 낮음 | 바쁘지만 잘 처리 중 | 정상적인 busy 상태 |
| util% 높음, await 높음, avgqu 높음 | 병목 가능성 높음 | 디스크 포화, 스토리지 한계, checkpoint 밀림 |
| util% 낮음, await 높음 | 순간 지연 | flush, fsync, burst I/O, 스토리지 응답 이상 |
| w/s, wkB/s 높음 | 쓰기 위주 부하 | checkpoint, WAL flush, 배치 |
| r/s, rkB/s 높음 | 읽기 위주 부하 | seq scan, 대량 조회, VACUUM scan |
| r/s, w/s 둘 다 높음 | read/write 혼합 부하 | VACUUM, 배치, ETL, 복합 워크로드 |
오늘은 여기까지~
728x90
'Linux' 카테고리의 다른 글
| Linux: 터미널 세션 기록 (1) | 2025.11.14 |
|---|---|
| Linux: rpm 다운로드 방법 (1) | 2025.08.04 |
| Linux: 커널 메모리 관리 파라미터 (1) | 2025.07.28 |
| Linux: 기본 디렉터리 구조 (2) | 2025.07.22 |
| Linux: OpenSSH 사용법 (0) | 2025.02.24 |