본문 바로가기
infra & cloud/linux

쉘스크립트와 엑셀을 사용한 로그 분석 : awk 사용

by 사용자 펭귄대장 2019. 4. 16.

보통 서버 로그를 분석하는 툴(awstats 등)을 서버내에 설치하거나

로그를 다운받은 후 로그 분석 툴을 돌려 로그를 분석하는 걸로 알고있다.

 

하지만 분석을 excel 로 할 테니, 서버 로그를 row 데이터로 뽑아 달라는 갑의 요구사항이 있었다..

(운영은 자기네들이 하면서 왜 이걸 나한테 하라고.....)

 

 

1. 로그에서 필요한 부분들만 발췌하여 row 데이터로 만들어 주는 shell script 를 짠다.

[로그 형식]

2019-04-15 18:50:37,511 INFO  [stdout] (default task-40) INFO : com.test.sample.interceptor.ControllerAOP - # RESPONSE | CONTROLLER = ApiController | METHOD = /mobile/api/getvoddata | RESULT = success | REMOTEADDR = 127.0.0.1 | PORT = 8082 | TIME = 9 ms | IN_PARAMS = {key1=value1, key2=value2, key3=value3} | OUT_PARAMS = {key1=value1, key2=value2}

서버 로그가 위와 같이 쌓이고 있다.

서버 로그에서 불필요한 부분들(검은색 폰트)은 제거하고 남길 데이터들(빨강색 폰트)만 row데이터로 남겨, txt 파일을 생성하는 shell script를 만들어보자.

 

makelowdata.sh 파일 생성

> touch makelowdata.sh 

makelowdata.sh 파일 vi 모드로 편집

> vi makelowdata.sh

 

쉘스크립트 실행시

첫번째 매개변수를 분석대상로그파일,

두번째 매개변수를 추출할 row 데이터의 시작기준시각,

세번째 매개변수를 추출할 row 데이터의 종료기준시각

으로 가정하고 작성

 

[작성 완료한 makelowdata.sh 쉘스크립트]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/bin/sh
LOG_FILE=$1
FROM_TIME=$2
END_TIME=$3
 
if [ $LOG_FILE ] ;
        then
        echo "LOG_FILE is null"
fi
 
if [ $FROM_TIME ] ;
        then
        echo "FROM_TIME is null"
fi
 
if [ $END_TIME ] ;
        then
        echo "END_TIME is null"
fi
 
 
echo "---------------------------------------"
echo "analysing logging starts... "
echo "target log file : $1"
 
if [ -f logrowdata_$2_$3.txt ] ;
       then
           echo "logrowdata_$2_$3 exists"
           exit
        else
           touch logrowdata_$2_$3.txt
fi
 
 
 
var1=`awk -v frd="$FROM_TIME" -v et="$END_TIME" 'frd <= $2 && $2 <= et' $LOG_FILE | grep -'success|fail' | sed 's/IN_PARAMS = //' | sed 's/OUT_PARAMS = //' | awk '{print $1 "\t" $2 "\t" $9 "\t" $16 "\t" $20 "\t" $24 "\t" $28 "\t" $32 "\t" $36}'`
var2=`awk -v frd="$FROM_TIME" -v et="$END_TIME" 'frd <= $2 && $2 <= et' $LOG_FILE | grep -'success|fail' | sed 's/IN_PARAMS = //' | sed 's/OUT_PARAMS = //' | cut -d'|' -f8-9 | sed 's/|/\t/'`
 
 
if [ -f var1.txt ] ;
     then
         rm ./var1.txt
fi
 
if [ -f var2.txt ] ;
     then
         rm ./var2.txt
fi
 
 
echo "$var1" > var1.txt
echo "$var2" > var2.txt
 
 
paste -"\t" var1.txt var2.txt > logrowdata_$2_$3.txt
 
 
 
 
 
 
rm var1.txt var2.txt
 
 
echo "analysing logging has been finished... "
echo "---------------------------------------"
 
cs

 

 

[해석]

6~9 line : 매개변수 1 유효성검사

11~14 line : 매개변수 2 유효성검사 (시간 형식 체크는 굳이 하지 않음..)

16~19 line : 매개변수 2 유효성검사 (시간 형식 체크는 굳이 하지 않음..)

26~32 line : 결과물인 logrowdata_시작시각_종료시각.txt 파일 존재여부 확인 후, 존재할 경우 해당 파일 삭제, 존재하지 않을 경우 파일 생성

-f filename : 파일 존재할 시 true 리턴

36 line : 로그 파일(매개변수 1)에서 필요부분 추출 후 var1 변수에 선언

[한 줄 씩 해석]

1) var1=

>> var1 변수 선언 및 저장

2) `awk -v frd="$FROM_TIME" -v et="$END_TIME" 'frd <= $2 && $2 <= et' $LOG_FILE | 

awk -v 변수="값" -v 변수="값" '정규식' 파일

>> 전역변수 $LOG_FILE 의 파일 중 2번째 필드($2) 가 frd 보다 크거나 같고 et 보다 작거나 같은 row만 뽑는다. 

>> 전역변수 $FROM_TIME, $END_TIME을 각각 frd, et 변수에 저장, awk 정규식 내에서 변수로 사용 (awk -v 옵션 사용)

3) grep -E 'success|fail' | 

grep -E '문자열 조건 문자열'

>>  2)번으로 부터 전달받은 문자열 중, success 혹은 fail 문자열이 포함된 row만 뽑는다. (grep -E 옵션 사용)

4) sed 's/IN_PARAMS = //' | 

sed 's/치환대상문자열/대체문자열/'

>> 3)번으로 부터 전달받은 문자열에서 "IN_PARAMS = " 값을 ""로 치환한다. (sed 's~' 사용)

sed 's/OUT_PARAMS = //' | 

>> 위와 동일

5) awk '{print $1 "\t" $2 "\t" $9 "\t" $16 "\t" $20 "\t" $24 "\t" $28 "\t" $32 "\t" $36}'`

>> 4) 단계 까지 처리한 row 에서 1,2,9,16,20,24,28,32,36 번째 필드를 중간중간 탭("\t") 구분자를 두어 출력 

 

37 line : 로그 파일(매개변수 1)에서 필요부분 추출 후 var2 변수에 선언

[한 줄 씩 해석]

1) var2=

>> var2 변수 선언 및 저장

2) `awk -v frd="$FROM_TIME" -v et="$END_TIME" 'frd <= $2 && $2 <= et' $LOG_FILE | 

awk -v 변수="값" -v 변수="값" '정규식' 파일

>> 전역변수 $LOG_FILE 의 파일 중 2번째 필드($2) 가 frd 보다 크거나 같고 et 보다 작거나 같은 row만 뽑는다. 

>> 전역변수 $FROM_TIME, $END_TIME을 각각 frd, et 변수에 저장, awk 정규식 내에서 변수로 사용 (awk -v 옵션 사용)

3) grep -E 'success|fail' | 

grep -E '문자열 조건 문자열'

>>  2)번으로 부터 전달받은 문자열 중, success 혹은 fail 문자열이 포함된 row만 뽑는다. (grep -E 옵션 사용)

4) sed 's/IN_PARAMS = //' | 

sed 's/치환대상문자열/대체문자열/'

>> 3)번으로 부터 전달받은 문자열에서 "IN_PARAMS = " 값을 ""로 치환한다. (sed 's~' 사용)

sed 's/OUT_PARAMS = //' | 

>> 위와 동일

5) cut -d'|' -f8-9 | 

cut -d'구분문자' -f추출할인덱스

>> 4) 단계 까지 처리한 row 에서 "|" 문자 기준으로 문자열을 분류하여(java split 함수와 비슷) 8~9 번째 문자열만 뽑는다. (cut -d -f 옵션 사용)

6) sed 's/|/\t/'` 

>> 5) 단계 까지 처리한 row 에서 "|" 문자열을 탭("\t")으로 치환

 

40~43 line : var1.txt 파일 존재시 삭제

45~48 line : var2.txt 파일 존재시 삭제

51 line : var1 변수를 var1.txt 파일로 생성

52 line : var2 변수를 var2.txt 파일로 생성

55 line : 탭("\t")을 구분으로 하여 var1.txt, var2.txt 파일을 합친 후(각각의 로우 기준으로 append), logrowdata_매개변수2_매개변수3.txt 파일로 저장

>> paste -d "\t" 파일1 파일2 > 결과파일 : -d 옵션을 사용하여 특정 문자를 구분자로 사용하여 두 문자열을 합친 후 결과파일로 생성

62 line : 임시 파일로 생성했던 var1.txt, var2.txt 를 삭제

 

 

2. 1번 쉘스크립트를 돌려 row 파일 생성

위에서 작성한 쉘스크립트 실행

> ./makelowdata.sh server.log 18:00 19:00

( server.log 로그파일에서 18:00 ~ 19:00시 사이의 로그만 추출 ) 

[쉘스크립트로 추출한 로그]

2019-04-15 18:30:37,511  com.test.sample.interceptor.ControllerAOP  ApiController  

/mobile/api/getvoddata  success  127.0.0.1  8082  9  {key1=value1, key2=value2, key3=value3}  {key1=value1, key2=value2}

 

3. 2번에서 생성한 row 파일을 엑셀 파일로 변환

1) 쉘스크립트로 생성한 txt 파일을 엑셀 파일로 연다.

2) "구분 기호로 분리됨" 선택, char encoding "949 : 한국어" 선택

3) 구분 기호 "탭" 선택

4) 열 데이터 서식 "텍스트" 선택

4. 필터등을 적용하여 분석한다.

분석은 알아서.

 

 

awk 로 로그 뽑을 줄 알았다면 로그 찍을 때 스페이스바 난사를 하지 않았을텐데.. 다음엔 이러지 말아야지.

책 사서 리눅스 공부도 해야겠다..

 

반응형

댓글2

  • 2020.07.13 18:04

    안녕하세요 자료 감사합니다.
    LOG_FILE=$1 여기부분에 파일 명을 넣으면 안되나요?
    답글

    • 안녕하세요.
      스크립트 LOG_FILE=$1 부분에서 $1 에 파일명을 직접 넣어도 되겠지만 log 파일명이 항상 동일한게 아니므로(지난날짜 로그에서 추출할 경우 파일명이 다름) 매개변수로 받게 해놓았습니다.

      예를 들어
      ./makelowdata.sh server.log 18:00 19:00
      라고 치시면
      스크립트에서
      $1 에 첫번째 매개변수인 server.log,
      $2 에 두번째 매개변수인 18:00,
      $3 에 세번째 매개변수인 19:00
      가 각각 매핑됩니다.
      또한 작성한 스크립트는 log format 에 따라 awk 를 달리 사용해야 합니다.