Created
August 1, 2025 04:05
-
-
Save junetech/2b5529940dbdb4389f0c5ce226302079 to your computer and use it in GitHub Desktop.
Linux stress test using stress-ng
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
set -euo pipefail | |
# ==================================================================== | |
# stress_ng_test.sh: 자동으로 Idle/Load 상태 측정, 로그 수집 및 요약 | |
# Usage: bash stress_ng_test.sh (권한 필요 시 sudo) | |
# ==================================================================== | |
# --- 온도 추출 함수 --- | |
get_temp() { | |
local file="$1" temp | |
# Tctl 등 신뢰할 수 있는 온도 라벨만 정확히 지정해서 찾음 | |
# 이렇게 하면 NVMe의 high limit 같은 관련 없는 값은 무시됨 | |
temp=$(grep -iE 'Tctl:' "$file" | grep -oE '[0-9]+(\.[0-9]+)?' | sort -nr | head -n1 || true) | |
if [[ -n "$temp" && "$temp" != "N/A" ]]; then | |
# 온도가 1000을 넘으면 millidegree로 간주하고 1000으로 나눔 (예: 85000 -> 85.0) | |
if command -v bc &>/dev/null && (( $(echo "$temp > 1000" | bc -l) )); then | |
temp=$(echo "scale=1; $temp / 1000" | bc -l) | |
fi | |
printf "%.1f" "$temp" | |
else | |
printf "N/A" | |
fi | |
} | |
# --- 사용자 설정 --- | |
DURATION=120 # 부하시 실행 시간(초) | |
ALL_CPU_COUNT=$(nproc) # CPU 코어 수 자동 탐지 | |
CUSTOM_CPU_COUNT=16 # 사용자 지정 CPU 코어 수 (0은 자동 탐지) | |
if [[ "$CUSTOM_CPU_COUNT" -gt 0 && "$CUSTOM_CPU_COUNT" -le "$ALL_CPU_COUNT" ]]; then | |
CPU_COUNT=$(( CUSTOM_CPU_COUNT < ALL_CPU_COUNT ? CUSTOM_CPU_COUNT : ALL_CPU_COUNT )) | |
else | |
CPU_COUNT="$ALL_CPU_COUNT" | |
fi | |
HOSTNAME=$(hostname) | |
TIMESTAMP=$(date +%Y%m%d_%H%M%S) | |
# --- 출력 파일명 정의 --- | |
IDLE_SENSORS="idle_sensors_${HOSTNAME}_${TIMESTAMP}.log" | |
IDLE_IPMI="idle_ipmi_${HOSTNAME}_${TIMESTAMP}.log" | |
IDLE_ENERGY="idle_energy_${HOSTNAME}_${TIMESTAMP}.log" | |
IDLE_FREQ="idle_freq_${HOSTNAME}_${TIMESTAMP}.log" | |
LOAD_SENSORS="load_sensors_${HOSTNAME}_${TIMESTAMP}.log" | |
LOAD_IPMI="load_ipmi_${HOSTNAME}_${TIMESTAMP}.log" | |
LOAD_ENERGY="load_energy_${HOSTNAME}_${TIMESTAMP}.log" | |
LOAD_FREQ="load_freq_${HOSTNAME}_${TIMESTAMP}.log" | |
THROTTLE_LOG="throttle_${HOSTNAME}_${TIMESTAMP}.log" | |
# --- 필수 도구 확인 (ipmitool과 dmesg는 optional) --- | |
for cmd in sensors stress-ng; do | |
if ! command -v "$cmd" &>/dev/null; then | |
echo "Error: '$cmd' 명령을 찾을 수 없습니다. 설치 후 재실행하세요." >&2 | |
exit 1 | |
fi | |
done | |
# ipmitool 유무 체크 | |
USE_IPMITOOL=true | |
if ! command -v ipmitool &>/dev/null; then | |
echo "Warning: 'ipmitool' 명령을 찾을 수 없습니다. IPMI 로그 생략" >&2 | |
USE_IPMITOOL=false | |
fi | |
# dmesg 접근 가능 여부 체크 | |
USE_DMESG=true | |
if ! dmesg &>/dev/null; then | |
echo "Warning: dmesg 접근 권한이 없습니다. Thermal 이벤트 로깅 생략" >&2 | |
USE_DMESG=false | |
fi | |
# --- Idle 상태 측정 --- | |
echo "[1/4] Idle 상태 측정..." | |
sensors > "$IDLE_SENSORS" | |
if $USE_IPMITOOL; then ipmitool sensor > "$IDLE_IPMI"; else echo "N/A" > "$IDLE_IPMI"; fi | |
if [[ -r /sys/class/powercap/intel-rapl:0/energy_uj ]]; then cat /sys/class/powercap/intel-rapl:0/energy_uj > "$IDLE_ENERGY"; else echo "N/A" > "$IDLE_ENERGY"; fi | |
if [[ -r /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ]]; then cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq > "$IDLE_FREQ"; else echo "N/A" > "$IDLE_FREQ"; fi | |
echo " -> Idle 로그 생성" | |
# --- CPU 부하 실행 --- | |
trap 'echo "Interrupted"; kill -TERM "$STRESS_PID" &>/dev/null; exit 1' INT TERM | |
echo "[2/4] CPU 부하 시작: stress-ng --cpu $CPU_COUNT --timeout ${DURATION}s" | |
stress-ng --cpu "$CPU_COUNT" --timeout "${DURATION}s" --metrics-brief & | |
STRESS_PID=$! | |
wait "$STRESS_PID" | |
echo " -> 부하 완료" | |
# --- Load 상태 측정 --- | |
echo "[3/4] Load 상태 측정..." | |
sensors > "$LOAD_SENSORS" | |
if $USE_IPMITOOL; then ipmitool sensor > "$LOAD_IPMI"; else echo "N/A" > "$LOAD_IPMI"; fi | |
if [[ -r /sys/class/powercap/intel-rapl:0/energy_uj ]]; then cat /sys/class/powercap/intel-rapl:0/energy_uj > "$LOAD_ENERGY"; else echo "N/A" > "$LOAD_ENERGY"; fi | |
if [[ -r /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq ]]; then cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq > "$LOAD_FREQ"; else echo "N/A" > "$LOAD_FREQ"; fi | |
if $USE_DMESG; then dmesg | grep -iE "thermal|throttl" > "$THROTTLE_LOG" || true; else echo "N/A" > "$THROTTLE_LOG"; fi | |
echo " -> Load 로그 생성" | |
# --- 결과 요약 --- | |
echo "[4/4] 결과 요약" | |
IDLE_TEMP=$(get_temp "$IDLE_SENSORS") | |
MAX_TEMP=$(get_temp "$LOAD_SENSORS") | |
# 수정된 코드 (더욱 안정적인 방식으로 쓰로틀 카운트) | |
if [[ -f "$THROTTLE_LOG" ]]; then | |
THROTTLE_COUNT=$(grep -c -iE 'thermal|throttl' "$THROTTLE_LOG") | |
else | |
THROTTLE_COUNT=0 | |
fi | |
echo " - Idle 온도: ${IDLE_TEMP}°C" | |
echo " - 부하 최대 온도: ${MAX_TEMP}°C" | |
echo " - 쓰로틀 이벤트 수: ${THROTTLE_COUNT}" | |
# 평균 전력 계산 | |
if command -v bc &>/dev/null && [[ -f "$IDLE_ENERGY" && -f "$LOAD_ENERGY" ]]; then | |
E_IDLE=$(cat "$IDLE_ENERGY") E_LOAD=$(cat "$LOAD_ENERGY") | |
if [[ "$E_IDLE" != "N/A" && "$E_LOAD" != "N/A" ]]; then | |
AVG_PWR=$(echo "scale=2;($E_LOAD-$E_IDLE)/($DURATION*1000000)" | bc -l) | |
echo " - 평균 전력: ${AVG_PWR} W" | |
fi | |
fi | |
# 워크로드 분류 (수정된 구문) | |
if command -v bc &>/dev/null && [[ "$MAX_TEMP" != "N/A" ]]; then | |
# bc를 사용하여 조건을 확인하고 결과를 변수에 저장 (1=참, 0=거짓) | |
IS_OVER_95=$(echo "$MAX_TEMP>=95" | bc -l) | |
IS_UNDER_90=$(echo "$MAX_TEMP<90" | bc -l) | |
# 표준 [[...]] 구문을 사용하여 명확하게 논리 검사 | |
if [[ "$IS_OVER_95" -eq 1 || "$THROTTLE_COUNT" -gt 0 ]]; then | |
CLASS="Thermal limit 워크로드" | |
elif [[ "$IS_UNDER_90" -eq 1 ]]; then | |
CLASS="안전 워크로드" | |
else | |
CLASS="주의 워크로드" | |
fi | |
echo " - 분류: $CLASS" | |
fi | |
echo -e "\n로그 파일 목록:" | |
printf '%s\n' "$IDLE_SENSORS" "$IDLE_IPMI" "$IDLE_ENERGY" "$IDLE_FREQ" \ | |
"$LOAD_SENSORS" "$LOAD_IPMI" "$LOAD_ENERGY" "$LOAD_FREQ" "$THROTTLE_LOG" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment