iBetter Books
수정

프로젝트 3: 서버 모니터링 대시보드

세 번째 프로젝트는 서버 모니터링입니다. CPU가 갑자기 100%로 치솟거나 디스크가 가득 차면 빠르게 알아야 합니다. 터미널에서 바로 현황을 확인하고, 임계값을 넘으면 색상으로 경고를 표시합니다.

요구사항

  • CPU, 메모리, 디스크, 네트워크 연결 수를 측정합니다.
  • 임계값은 설정 파일에서 읽습니다.
  • 정상은 초록, 경고는 노랑, 위험은 빨강으로 표시합니다.
  • 측정값을 CSV 형식으로 기록합니다.

설정 파일

# 새 파일: /home/ubuntu/scripts/monitor.conf# CPU 사용률 임계값 (%)CPU_WARN=70CPU_CRIT=90# 메모리 사용률 임계값 (%)MEM_WARN=80MEM_CRIT=95# 디스크 사용률 임계값 (%)DISK_WARN=80DISK_CRIT=90# 네트워크 연결 수 임계값NET_WARN=500NET_CRIT=1000# CSV 히스토리 파일HISTORY_FILE="/tmp/server_monitor_history.csv"# 히스토리 보관 줄 수 (0이면 무제한)HISTORY_MAX_LINES=1000

모니터링 스크립트

#!/usr/bin/env bash# 새 파일: /home/ubuntu/scripts/server_monitor.shset -euo pipefail# ==============================================================# 설정 파일 로드# ==============================================================SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"CONFIG_FILE="${SCRIPT_DIR}/monitor.conf"if [[ -f "$CONFIG_FILE" ]]; then    source "$CONFIG_FILE"else    # 기본값    CPU_WARN=70;  CPU_CRIT=90    MEM_WARN=80;  MEM_CRIT=95    DISK_WARN=80; DISK_CRIT=90    NET_WARN=500; NET_CRIT=1000    HISTORY_FILE="/tmp/server_monitor_history.csv"    HISTORY_MAX_LINES=1000fi# ==============================================================# 색상 정의# ==============================================================RED='\033[0;31m'YELLOW='\033[1;33m'GREEN='\033[0;32m'CYAN='\033[0;36m'BOLD='\033[1m'RESET='\033[0m'# ==============================================================# 색상 판단 함수# ==============================================================# 사용법: color_status <현재값> <경고임계값> <위험임계값>color_status() {    local value="$1"    local warn="$2"    local crit="$3"    local int_value="${value%.*}"  # 소수점 제거    if (( int_value >= crit )); then        echo -e "${RED}"    elif (( int_value >= warn )); then        echo -e "${YELLOW}"    else        echo -e "${GREEN}"    fi}print_metric() {    local label="$1"    local value="$2"    local unit="$3"    local warn="$4"    local crit="$5"    local extra="${6:-}"    local color    color=$(color_status "$value" "$warn" "$crit")    local int_value="${value%.*}"    local status_icon    if (( int_value >= crit )); then        status_icon="[위험]"    elif (( int_value >= warn )); then        status_icon="[경고]"    else        status_icon="[정상]"    fi    printf "  ${BOLD}%-20s${RESET} ${color}%6s%s  %s${RESET}  %s\n" \        "$label" "$value" "$unit" "$status_icon" "$extra"}# ==============================================================# 지표 수집 함수# ==============================================================get_cpu_usage() {    # top을 2회 실행 후 두 번째 결과로 더 정확한 값 측정    top -bn2 | grep "Cpu(s)" | tail -1 | awk '{        # idle이 4번째 숫자 - 100에서 빼면 사용률        for(i=1;i<=NF;i++) if($i ~ /id,/) { idle=$(i-1); break }        printf "%.1f", 100 - idle    }'}get_mem_usage() {    free | awk 'NR==2{        used=$3; total=$2        printf "%.1f", used/total*100    }'}get_mem_detail() {    free -h | awk 'NR==2{print $3 "/" $2}'}get_disk_usage() {    df / | awk 'NR==2{print $5}' | tr -d '%'}get_disk_detail() {    df -h / | awk 'NR==2{print $3 "/" $2}'}get_net_connections() {    ss -tun 2>/dev/null | grep -c "ESTAB" || echo "0"}get_load_avg() {    uptime | awk -F'load average:' '{print $2}' | tr -d ' '}# ==============================================================# 대시보드 출력# ==============================================================clearTIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')HOSTNAME=$(hostname)echo -e "${BOLD}${CYAN}"echo "╔══════════════════════════════════════════════════╗"echo "║          서버 모니터링 대시보드                  ║"echo "╚══════════════════════════════════════════════════╝"echo -e "${RESET}"echo -e "  호스트: ${BOLD}${HOSTNAME}${RESET}   시간: ${TIMESTAMP}"echo "  부하 평균: $(get_load_avg)"echo ""echo -e "${BOLD}  지표                   현재값   상태     상세${RESET}"echo "  ─────────────────────────────────────────────────"# 지표 수집CPU=$(get_cpu_usage)MEM=$(get_mem_usage)MEM_DETAIL=$(get_mem_detail)DISK=$(get_disk_usage)DISK_DETAIL=$(get_disk_detail)NET=$(get_net_connections)# 출력print_metric "CPU 사용률" "$CPU" "%" "$CPU_WARN" "$CPU_CRIT"print_metric "메모리 사용률" "$MEM" "%" "$MEM_WARN" "$MEM_CRIT" "($MEM_DETAIL)"print_metric "디스크 사용률" "$DISK" "%" "$DISK_WARN" "$DISK_CRIT" "($DISK_DETAIL)"print_metric "네트워크 연결" "$NET" "개" "$NET_WARN" "$NET_CRIT"echo ""# ==============================================================# CSV 히스토리 기록# ==============================================================# 헤더가 없으면 추가if [[ ! -f "$HISTORY_FILE" ]]; then    echo "timestamp,cpu,mem,disk,net_connections" > "$HISTORY_FILE"fiecho "${TIMESTAMP},${CPU},${MEM},${DISK},${NET}" >> "$HISTORY_FILE"# 히스토리 줄 수 제한if [[ "${HISTORY_MAX_LINES:-0}" -gt 0 ]]; then    CURRENT_LINES=$(wc -l < "$HISTORY_FILE")    if (( CURRENT_LINES > HISTORY_MAX_LINES + 1 )); then        # 헤더 보존하면서 오래된 줄 제거        HEADER=$(head -1 "$HISTORY_FILE")        TAIL_LINES=$(tail -n "$HISTORY_MAX_LINES" "$HISTORY_FILE")        { echo "$HEADER"; echo "$TAIL_LINES"; } > "${HISTORY_FILE}.tmp"        mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"    fifiecho -e "  히스토리: ${HISTORY_FILE}"echo ""

실행 결과

chmod +x /home/ubuntu/scripts/server_monitor.sh/home/ubuntu/scripts/server_monitor.sh

터미널에서 보이는 결과입니다.

╔══════════════════════════════════════════════════╗
║          서버 모니터링 대시보드                  ║
╚══════════════════════════════════════════════════╝

  호스트: myserver   시간: 2026-04-24 09:20:01
  부하 평균: 0.15, 0.12, 0.10

  지표                   현재값   상태     상세
  ─────────────────────────────────────────────────
  CPU 사용률              3.2%  [정상]
  메모리 사용률          45.8%  [정상]  (1876M/4096M)
  디스크 사용률            34%  [정상]  (17G/50G)
  네트워크 연결             3개  [정상]

  히스토리: /tmp/server_monitor_history.csv

정상 구간은 초록, 경고 구간은 노랑, 위험 구간은 빨강으로 표시됩니다. 실제 터미널에서 실행하면 색상이 보입니다.

CSV 히스토리 확인

cat /tmp/server_monitor_history.csv
timestamp,cpu,mem,disk,net_connections
2026-04-24 09:20:01,3.2,45.8,34,3
2026-04-24 09:25:01,2.8,46.1,34,4
2026-04-24 09:30:01,4.5,46.3,34,3

crontab 등록

crontab -e
# 5분마다 서버 상태 기록 (대시보드 없이 히스토리만)
*/5 * * * * /home/ubuntu/scripts/server_monitor.sh > /dev/null 2>&1