텍스트처리_12 웹 접속 로그에서 파일별 접속 횟수 집계하기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: awk, sort, uniq
키워드: 접속 로그, 로그 분석, 페이지 뷰
사용처: 아파치 접속 로그에서 페이지 뷰를 집계하고 싶을 때


실행예제

$ cat access.log
xx.xx.xx.xx - - [06/Jan/2014:05:58:35 +0900] "GET / HTTP/1.1" 200 83 "-" "-"
yy.yy.yy.yy - - [06/Jan/2014:06:01:43 +0900] "GET /index.html HTTP/1.1" 200 304
yy.yy.yy.yy - - [06/Jan/2014:06:01:44 +0900] "GET /title.gif HTTP/1.1" 200 763
(생략)

$ ./log-accessfile.sh
29	/news.html
22	/
18	/favicon.ico
 8	/menu
 8	/title.gif
(생략)

스크립트

#!/bin/sh
 
logfile="access_log"
 
# 로그 파일이 존재하지 않으면 종료
if [ ! -f "$logifle" ]; then  #----------------------------------------- 1(if문)
    echo "대상 로그 파일이 존재하지 않습니다 : $logfile" >&2
    exit 1
fi

# 로그 파일에서 GET 메소드로 취득한 파일 접속 횟수 집계
# awk 명령어로 파일을 추출해서 sort+uniq으로 카운트해서 역순 정렬
awk '$6=="\"GET" {print $7}' "$logfile" | sort | uniq -c | sort -nr  #-- 2

   

해설

이 스크립트는 아파치 접속 로그에서 파일별 접속 수를 집계합니다. 웹 페이지를 운영할 때 페이지 뷰(PV)를 조사하는 것은 무척 중요한 업무입니다. 우선 이런 간단한 스크립트로 집계 리포트를 정기적으로 취득해두면 많은 정보를 얻을 수 있을 겁니다.

이 예제에서는 아파치 아파치 접속 로그가 아래와 같다고 가정합니다.

  • 파일1 아파치 common 형식 로그 예
    192.168.1.1 - - [06/Jan/2014:05:58:35 +0900] "GET /index.html HTTP/1.1" 200 83
    

스크립트에서는 “ “로 둘러싼 HTTP 리퀘스트에서 파일명을 취득합니다. HTTP 리퀘스트에는 다양한 메소드가 있지만 여기에서는 GET 메소드로 취득한 접속만 집계합니다. 자주 보는 HTTP 메소드는 아래와 같습니다. 이것은 RFC 2616에 정의되어 있습니다.

  • 흔히 볼 수 있는 HTTP 메소드

    메소드명 이용 장면
    GET URI로 지정한 파일 취득
    HEAD HTTP 헤더만 취득하고 메시지 보디는 취득하지 않음
    POST 메시지 투고 등을 함
    PUT 파일 송신
    CONNECT SSL 통신을 하는 등 프록시에 터널을 요구함

1에서 대상 로그 파일 존재를 확인합니다. -f는 대상이 일반 파일인지 확인하는 연산자입니다. 거기에 부정 연산자 !와 함께 써서 대상이 디렉터리이거나 파일이 존재하지 않으면 에러를 표시하고 종료합니다.

2에서 파일마다 접속 수를 카운트합니다. 여기서 GET 메소드로 취득한 리퀘스트만이 대상이므로 awk 명령어 필터로 HTTP 메소드가 들어 있는 여섯 번째 컬럼에 대해 “GET” 으로 필터를 지정합니다. 그리고 2에서는 따옴표를 이스케이프하므로 실제로는 $6==”"GET”이 됩니다. 정상적으로 메소드가 지정되면 접속 로그에서 7번째 컬럼이 파일명이므로 awk 명령어를 실행하면 {print $7}로 출력합니다.

그리고 2에서는 awk 명령어 출력을 일단 sort 명령어로 정렬해서 파이프 마지막에 한번 더 sort 명령어 -n 옵션(숫자 정렬)과 -r 옵션(역순 정렬)으로 실행해서 접속이 많은 순서대로 표시합니다. 이 sort 명령어와 uniq 명령어 조합을 사용해서 파일별 접속 로그 줄 수 즉, 파일별 페이지 뷰가 많은 순서대로 파일명을 표시할 수 있습니다.

그리고 여기에서는 “GET”이라는 필터를 걸어서 조금 이상한 접속 로그를 제거하려고 합니다. 실제로 웹 서버를 운용하다 보면 다음과 같은 이상한 접속을 볼 수 있습니다.

xx.xx.xx.xx - - [12/Apr/2021:18:34:56 +0900] "\x80w\x10\x03\x01" 501 294

원래라면 HTTP 사양에 따라 리퀘스트는 GET이나 POST 같은 메소드명으로 시작해야 하지만 이 로그는 갑자기 이상한 문자열로 접속하고 있습니다.

이것은 http 포트에 https 접속을 하려고 하는 SSL 통신을 그대로 http에 보냈을 때 나타나는 접속 로그입니다. 단순히 클라이언트가 잘못했거나 또는 공격자가 의도적으로 스캔했을 수도 있습니다. 그 외에도 공격을 위해 HTTP 사양을 위반해서 에러가 발생해야 할 리퀘스트를 보내는 접속 로그가 있을 수도 있습니다. 따라서 이 예제에는 필터로 이런 로그를 제거했습니다.

공개된 웹 서버에는 다양한 접속이 발생하므로 집계할 때 어느 정도 잘못된 정보가 들어갈 수도 있다는걸 감수해야 합니다.

   

주의사항

  • 웹 서버 아파치는 널리 사용되는 소프트웨어로 로그 분석툴도 많습니다. 자주 사용하는 유명한 툴로 AWStats가 있습니다. 로그를 그래프화하거나 시각적으로 알기 쉽게 만들어주므로 이용해보기 바랍니다.