Engineering/Network

Nginx access 로그 에서 특정 필드만 추출하는 스크립트

부스 boos 2026. 5. 21. 18:11
728x90

 Nginx 에서 다음과 같이 access 로그 포맷을 사용 중이다. (일반적으로 Nginx 설치하면 기본 설정된 내용)

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

 

 access 로그는 다음과 같이 나오고 있다.

...
192.168.1.153 - - [19/May/2026:22:10:26 +0900] "GET /upload/1/d06dbb6.zzz?filename=test.abc HTTP/2.0" 200 307787981 "https://receive.tt.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36" "-"
192.168.1.11 - - [19/May/2026:22:13:05 +0900] "GET /upload/3/d06dbb6.zzz?test2.abc HTTP/2.0" 200 312624831 "https://receive.tt.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36" "-"
192.168.1.15 - - [19/May/2026:22:25:21 +0900] "GET /upload/5/test3.zzz HTTP/2.0" 200 312624831 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36" "-"
...

 

 로그의 필드 중에서 $remote_addr, $time_local(시간 포맷은 yyyy-mm-dd HH:MM:ss), $request, $http_referer, $http_user_agent 만 따로 뽑아서 보고 싶어서 다음과 같이 AI 를 통해서 perl 스크립트를 작성했다.

 

#!/bin/bash

# 입력 인자(로그 파일 경로) 확인
if [ -z "$1" ]; then
    echo "사용법: $0 <로그_파일_경로>"
    exit 1
fi

if [ ! -f "$1" ]; then
    echo "오류: '$1' 파일을 찾을 수 없습니다."
    exit 1
fi

# Perl 정규식을 이용해 각 필드를 정확하게 그룹화하여 추출
perl -ne '
BEGIN {
    # 월 이름 변환용 해시 사전 세팅
    %months = (Jan=>"01", Feb=>"02", Mar=>"03", Apr=>"04", May=>"05", Jun=>"06",
               Jul=>"07", Aug=>"08", Sep=>"09", Oct=>"10", Nov=>"11", Dec=>"12");
}

# Nginx 포맷을 정교하게 분석하는 정규식
if (/^(\S+) \S+ \S+ \[(\d+)\/(\w+)\/(\d+):([\d:]+) [^\]]+\] "([^"]+)" \d+ \d+ "([^"]+)" "([^"]+)"/) {
    $ip = $1;
    $day = $2;
    $mon = $months{$3};
    $year = $4;
    $time = $5;
    $req = $6;
    $ref = $7;
    $ua = $8;

    # YYYY-MM-DD hh:mm:ss 포맷 생성
    $formatted_time = "$year-$mon-$day $time";

    # 특정 5개 필드만 한 줄로 출력 
    print "\"$ip\",\"$formatted_time\",\"$req\",\"$ref\",\"$ua\"\n";
}
' "$1"

 

  사용법은 "parse_log.sh [access.log] " 형식으로 하면 표준 출력으로 결과가 나온다.

ex) ./parse_log.sh access.log > out.csv