반응형

왜 서버 일일 점검을 자동화해야 할까?

리눅스 서버를 운영하다 보면 매일 반복해야 하는 점검 항목들이 있습니다. CPU 사용률은 정상인지, 디스크가 꽉 차가고 있지는 않은지, 핵심 서비스는 살아있는지 — 이걸 매일 수작업으로 확인하는 건 시간 낭비이자 실수의 원인이 됩니다. Bash 쉘 스크립트와 cron을 조합하면 이 모든 점검을 완전 자동화하고, 이상 발생 시 즉시 알림까지 받을 수 있습니다.

이 글에서는 실무에서 바로 쓸 수 있는 Daily Check 스크립트를 단계별로 구성하는 방법을 다룹니다.

점검 항목 설계

일일 점검 스크립트는 크게 5가지 영역을 커버해야 합니다.

  • 시스템 리소스: CPU, 메모리, Load Average
  • 디스크 사용량: 마운트 포인트별 사용률
  • 서비스 상태: nginx, mysql, sshd 등 핵심 데몬
  • 네트워크: 포트 오픈 여부, 외부 통신 가능 여부
  • 로그 이상 감지: /var/log/syslog에서 ERROR, CRITICAL 키워드 탐지

스크립트 전체 구조

아래는 실무에서 사용할 수 있는 daily_check.sh의 전체 구조입니다. 각 섹션별로 함수로 분리해서 유지보수가 쉽게 작성했습니다.

기본 설정 및 변수 선언

#!/bin/bash
# daily_check.sh — 리눅스 서버 일일 점검 스크립트

DATE=$(date '+%Y-%m-%d %H:%M:%S')
HOSTNAME=$(hostname)
LOG_FILE="/var/log/daily_check.log"
ALERT_EMAIL="admin@example.com"
CPU_THRESHOLD=80
MEM_THRESHOLD=85
DISK_THRESHOLD=90

RESULT=""
ALERT=0

log() {
  echo "[$DATE] $1" | tee -a "$LOG_FILE"
  RESULT+="$1\n"
}

CPU / 메모리 점검 함수

check_cpu() {
  log "=== CPU 점검 ==="
  CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1 | cut -d',' -f1)
  CPU_INT=${CPU_USAGE%.*}
  if [ "$CPU_INT" -ge "$CPU_THRESHOLD" ]; then
    log "[WARNING] CPU 사용률 높음: ${CPU_USAGE}%"
    ALERT=1
  else
    log "[OK] CPU 사용률: ${CPU_USAGE}%"
  fi
}

check_memory() {
  log "=== 메모리 점검 ==="
  MEM_TOTAL=$(free -m | awk '/Mem:/{print $2}')
  MEM_USED=$(free -m | awk '/Mem:/{print $3}')
  MEM_PERCENT=$(echo "scale=1; $MEM_USED * 100 / $MEM_TOTAL" | bc)
  MEM_INT=${MEM_PERCENT%.*}
  if [ "$MEM_INT" -ge "$MEM_THRESHOLD" ]; then
    log "[WARNING] 메모리 사용률 높음: ${MEM_PERCENT}% (${MEM_USED}MB / ${MEM_TOTAL}MB)"
    ALERT=1
  else
    log "[OK] 메모리 사용률: ${MEM_PERCENT}%"
  fi
}

디스크 점검 함수

check_disk() {
  log "=== 디스크 점검 ==="
  df -h --output=pcent,target | tail -n +2 | while read -r line; do
    USAGE=$(echo "$line" | awk '{print $1}' | tr -d '%')
    MOUNT=$(echo "$line" | awk '{print $2}')
    if [ "$USAGE" -ge "$DISK_THRESHOLD" ]; then
      log "[WARNING] 디스크 사용률 높음: $MOUNT — ${USAGE}%"
      ALERT=1
    else
      log "[OK] $MOUNT — ${USAGE}%"
    fi
  done
}

서비스 상태 점검 함수

SERVICES=("nginx" "mysql" "sshd" "cron")

check_services() {
  log "=== 서비스 상태 점검 ==="
  for SERVICE in "${SERVICES[@]}"; do
    if systemctl is-active --quiet "$SERVICE"; then
      log "[OK] $SERVICE: 실행 중"
    else
      log "[CRITICAL] $SERVICE: 중지됨!"
      ALERT=1
    fi
  done
}

로그 이상 감지 및 알림 발송

check_logs() {
  log "=== 로그 이상 감지 ==="
  ERROR_COUNT=$(grep -c -iE "error|critical|failed" /var/log/syslog 2>/dev/null || echo 0)
  log "최근 syslog ERROR/CRITICAL 건수: ${ERROR_COUNT}건"
  if [ "$ERROR_COUNT" -gt 10 ]; then
    log "[WARNING] 오류 로그 다수 감지"
    ALERT=1
  fi
}

send_alert() {
  if [ "$ALERT" -eq 1 ]; then
    echo -e "$RESULT" | mail -s "[ALERT] $HOSTNAME 일일 점검 이상 감지 — $DATE" "$ALERT_EMAIL"
    log "알림 이메일 발송 완료: $ALERT_EMAIL"
  else
    log "모든 점검 정상. 알림 없음."
  fi
}

# 메인 실행
log "=============================="
log "서버 일일 점검 시작: $HOSTNAME"
log "=============================="
check_cpu
check_memory
check_disk
check_services
check_logs
send_alert
log "점검 완료"

cron으로 매일 자동 실행 설정

스크립트 작성이 끝났다면 실행 권한을 부여하고 cron에 등록합니다.

chmod +x /usr/local/bin/daily_check.sh
crontab -e

crontab에 아래 줄을 추가하면 매일 오전 8시에 자동 실행됩니다.

0 8 * * * /usr/local/bin/daily_check.sh >> /var/log/daily_check.log 2>&1

실무 활용 팁

  • 알림 채널 확장: mail 대신 curl로 Slack Webhook이나 Telegram Bot API를 호출하면 모바일로 즉시 알림을 받을 수 있습니다.
  • 점검 항목 모듈화: 함수 단위로 분리되어 있으므로 서버 역할에 따라 필요한 함수만 골라서 실행할 수 있습니다.
  • 로그 로테이션: logrotate 설정으로 daily_check.log가 무한정 쌓이지 않도록 관리하세요.
  • 임계값 외부화: 임계값 변수를 별도 설정 파일(.conf)로 분리하면 스크립트 수정 없이 값을 바꿀 수 있습니다.

마무리

Bash 스크립트 하나로 CPU, 메모리, 디스크, 서비스, 로그까지 한 번에 점검하고 이상 시 자동 알림까지 보내는 시스템을 구축할 수 있습니다. 처음에는 단순한 스크립트로 시작해서 운영 환경에 맞게 점진적으로 확장하는 것이 가장 현실적인 접근 방법입니다. 서버가 늘어날수록 자동화의 가치는 더욱 커집니다.

반응형

+ Recent posts