워드프레스 웹페이지 404 에러 로그 수집방법

워드프레스 등을 운영하다가 보면 여러 공격에 노출이 될 수도 있고 제대로 설정을 안 할 경우에는 취약점에도 노출이 많이 될 수도 있다. 이번에는 404 에러 로그를 스크립트로 쉽게 수집하는 방법에 대해서 알아보려고 한다.


스크립트 작성 이전 아래 블로그 링크를 통해서 기본적인 에러에 대한 정의를 읽어 보시는 것을 추천해 드립니다.

미리 완성된 스크립트를 먼저 확인해 보겠습니다.

#!/bin/bash

LOG_FILE="/pathlogs/access_log"
ERROR_LOG="/path/auto/Web_404-error"
ERROR_DETAIL_LOG="/path/Web_404-error-detail"

CURRENT_TIME=$(date '+%d/%b/%Y:%H:%M')
FIVE_MIN_AGO=$(date --date='-5 min' '+%d/%b/%Y:%H:%M')
 
COUNT=$(awk -v start="$FIVE_MIN_AGO" -v end="$CURRENT_TIME" '($4 > "["start) && ($4 < "["end) && ($9 ~ /^(400|404)$/)' "$LOG_FILE" | wc -l)

FORMATTED_CURRENT_TIME=$(date '+%Y_%m_%d-%H:%M')

if [ "$COUNT" -gt 15 ]; then
          echo "$FORMATTED_CURRENT_TIME [5Min < $COUNT CountOver] ERROR" >> "$ERROR_LOG"

            # Count Over time log save -> bitnami/auto directory 
              awk -v start="$FIVE_MIN_AGO" -v end="$CURRENT_TIME" '($4 > "["start) && ($4 < "["end) && ($9 ~ /^(400|404)$/)' "$LOG_FILE" >> "$ERROR_DETAIL_LOG"
      else
                echo "$FORMATTED_CURRENT_TIME [5Min = $COUNT]" >> "$ERROR_LOG"
fi

먼저 완성된 코드를 확인하고 한줄 한줄 설명하겠습니다.

로그 수집 이전에는 자신의 웹 로그가 어디에 저장이 되는지 확인이 필요합니다.

스크립트 설명

Bash 셸 스크립트의 시작을 나타냅니다. 이 스크립트는 Bash 셸에서 실행

#!/bin/bash



스크립트에서 사용할 로그 파일의 경로와 에러 로그 파일의 경로를 정의 LOG_FILE은 Apache 웹 서버의 접근 로그 파일 경로, ERROR_LOG는 404 에러 발생 수를 기록할 로그 파일 경로, ERROR_DETAIL_LOG는 404 에러 발생 내역을 자세히 기록할 로그 파일 경로

LOG_FILE="/pathlogs/access_log"
ERROR_LOG="/path/auto/Web_404-error"
ERROR_DETAIL_LOG="/path/Web_404-error-detail"



현재 시간과 5분 전 시간을 변수에 저장하고 있습니다. CURRENT_TIME은 현재 시간을, FIVE_MIN_AGO는 현재 시간에서 5분을 뺀 시간을 나타냅니다.

CURRENT_TIME=$(date '+%d/%b/%Y:%H:%M')
FIVE_MIN_AGO=$(date --date='-5 min' '+%d/%b/%Y:%H:%M')



Apache 접근 로그 파일에서 최근 5분 동안 발생한 404 에러 수를 counting하는 부분입니다. awk 명령어를 사용하여 로그 파일에서 특정 조건에 해당하는 행을 찾아 그 개수를 COUNT 변수에 저장하는 구문

로그 파일에서 지정된 시간 범위 내의 400 및 404 에러 수를 카운트하는 역할을 합니다.

  • awk: 텍스트 파일을 처리하는 강력한 명령줄 도구
  • -v start=”$FIVE_MIN_AGO”: awk에 start 변수를 전달하여 5분 전 시간을 지정
  • -v end=”$CURRENT_TIME”: awk에 end 변수를 전달하여 현재 시간을 지정
  • ‘($4 > “[“start) && ($4 < “[“end)’: 4번째 필드(시간 정보)가 start와 end 사이에 있는 행을 선택
  • ($9 ~ /^(400|404)$/): 9번째 필드(상태 코드)가 400 또는 404인 행을 선택
  • “$LOG_FILE”: 처리할 로그 파일 경로
  • | wc -l: 선택된 행의 수를 카운트

이렇게 로그 파일에서 지정된 시간 범위 내의 400 및 404 에러 수를 COUNT 변수에 저장하게 됩니다.

COUNT=$(awk -v start="$FIVE_MIN_AGO" -v end="$CURRENT_TIME" '($4 > "["start) && ($4 < "["end) && ($9 ~ /^(400|404)$/)' "$LOG_FILE" | wc -l)



현재 시간을 YYYY_mm_dd-HH:MM 형식으로 변환하여 FORMATTED_CURRENT_TIME 변수에 저장

시스템의 현재 날짜와 시간을 특정 형식으로 변환하여 변수에 저장하는 명령어입니다.

  • date ‘+%Y_%m_%d-%H:%M’
    • date 명령어를 통해 현재 시간을 가져옵니다.
    • ‘+%Y_%m_%d-%H:%M’ 부분은 시간 형식을 지정하는 부분입니다.
      • %Y: 4자리 연도
      • %m: 2자리 월
      • %d: 2자리 일
      • %H: 24시간제 시
      • %M: 분
    • 이 형식으로 시간이 출력되며, 언더바(_)와 하이픈(-)을 사용하여 날짜와 시간을 구분하는 형태로 표현됩니다.
  • FORMATTED_CURRENT_TIME=
    • 위에서 구한 시간 형식을 FORMATTED_CURRENT_TIME이라는 변수에 할당합니다.
FORMATTED_CURRENT_TIME=$(date '+%Y_%m_%d-%H:%M')


최근 5분 동안 발생한 404 에러 수가 15개를 초과했는지 확인하는 조건문입니다.

  • 404 에러 수가 15개를 초과한 경우:
    • $FORMATTED_CURRENT_TIME [5Min < $COUNT CountOver] ERROR를 $ERROR_LOG 파일에 기록합니다.
    • 그리고 awk 명령어를 사용하여 최근 5분 동안의 404 에러 상세 내역을 $ERROR_DETAIL_LOG 파일에 기록합니다.
  • 404 에러 수가 15개 이하인 경우:
    • $FORMATTED_CURRENT_TIME [5Min = $COUNT]를 $ERROR_LOG 파일에 기록합니다.

여기서 15개 이상 이하 둘다 저장하는 이유는 추후 로그 확인 및 대처를 하기 위한 방식으로 15개 이하의 조건문을 제거하셔서 사용하셔도 됩니다.

if [ "$COUNT" -gt 15 ]; then
          echo "$FORMATTED_CURRENT_TIME [5Min < $COUNT CountOver] ERROR" >> "$ERROR_LOG"

            # Count Over time log save -> bitnami/auto directory 
              awk -v start="$FIVE_MIN_AGO" -v end="$CURRENT_TIME" '($4 > "["start) && ($4 < "["end) && ($9 ~ /^(400|404)$/)' "$LOG_FILE" >> "$ERROR_DETAIL_LOG"
      else
                echo "$FORMATTED_CURRENT_TIME [5Min = $COUNT]" >> "$ERROR_LOG"
fi

이와 같은 스크립트를 통해 워드프레스나 다른 웹 애플리케이션 운영 시 발생할 수 있는 404 에러를 효과적으로 모니터링하고 관리할 수 있습니다. 정기적으로 로그를 확인하여 문제의 원인을 파악하고 적절한 조치를 취함으로써, 웹 사이트의 안정성과 사용자 경험을 향상시킬 수 있습니다.

해당 스크립트 작성이 끝나셨으면 crontab을 통해서 시간을 지정해주시면 됩니다. 제가 적용한 범위는 5분입니다.

*/5 * * * * /path/auto/404-ERROR.sh

By Low ahn

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다