[Shell Script] 다중 원격 서버 로그 분석 자동화 스크립트

안녕하세요. 오늘은 여러 대의 애플리케이션 서버(AP)에 분산되어 쌓이는 로그를 매번 접속하지 않고, 한 번의 명령으로 취합하여 분석할 수 있는 유용한 셸 스크립트(analLog.sh)를 공유합니다.

이 스크립트는 특히 다수의 서버에서 특정 BPEL 프로세스의 완료 로그를 찾아 실행 시간 통계(최소, 최대, 평균 시간)를 빠르게 확인해야 할 때 매우 유용합니다.

스크립트의 주요 기능

analLog.sh 스크립트는 4대의 지정된 원격 서버(AP1~AP4)에 ssh로 자동 접속하여 다음 작업을 수행합니다.

  1. 로그 필터링: 사용자가 지정한 디렉터리(-f)에서 특정 메시지명(-m)을 포함하는 BPEL COMPLETED 로그를 검색합니다.
  2. 시간대 지정: 지정된 날짜(-d)와 시간(-t) 패턴에 일치하는 로그만 추출합니다.
  3. 성능 데이터 추출: 로그에 기록된 Elapsed time = [숫자] miliseconds 패턴을 찾아 실행 시간(숫자) 값만 파싱합니다.
  4. 통계 집계: awk를 사용하여 각 서버별 및 전체 서버의 **총 로그 건수(Count), 최소 시간(Min), 최대 시간(Max), 평균 시간(Avg)**을 밀리초(ms) 단위로 계산합니다.
  5. (선택) 분당/초당 처리량: -l [분] 옵션을 제공하면, 지정한 시간(분)을 기준으로 분당 및 초당 평균 처리 건수를 함께 계산해 줍니다.

사용 방법 (Usage)

스크립트는 getopts를 사용하여 표준 옵션 인자를 받습니다.

Bash
Usage: analLog.sh -m [MESSAGE] -d [DATE] -t [TIME] -f [DIRECTORY]
Try 'analLog.sh -help' for more information.

옵션 상세:

  • -m: 검색할 메시지 이름 (예: AlarmReport.bpel)
  • -d: 검색할 날짜 (예: 20/07/02)
  • -t: 검색할 시간 (예: 01:17: 또는 01:[0-9][0-9]:)
  • -f: 검색할 원격 서버의 로그 디렉터리 경로 (예: /mesap_log/EEXsvr/20200702)
  • -l (선택 사항): 분석 대상 시간(분). (예: 60)

실행 예시:

Bash
./analLog.sh -m AlarmReport.bpel -d 25/10/21 -t 08:15: -f /mesap_log/EEXsvr/20251021

전체 스크립트 코드

Bash
#!/bin/bash

### Created by Ho Seop Lee of Aim System.

### Initialization

usageMsg="Usage: analLog.sh -m [MESSAGE] -d [DATE] -t [TIME] -f [DIRECTORY]
Try 'analLog.sh -help' for more information."

helpMsg='
\t-m\t\tMessage Name\t(ex: -m AlarmReport.bpel)
\t-d\t\tDate\t\t(ex: -d 20/07/02)
\t-t\t\tTime\t\t(ex: -t 01:17: or -t 01:[0-9][0-9]:)
\t-f\t\tDirectory Path\t(ex: -f /mesap_log/EEXsvr/ or -f /mesap_log/EEXsvr/20200702)
\t-l (Optional)\tMinutes should be analyzed\t(ex: -l 60)
\t-h, -help, -?\tShow Help Info
'

cols=`tput cols`

for((i=0; i<$cols; i++));
do
    line=$line'=';
done

function printLine()
{
    echo $line
}

usage()
{
    echo -e "$usageMsg"
    printLine
    exit 0
}

help()
{
    echo -e "$helpMsg"
    printLine
    exit 0
}

printLine

### Declaration Option Argument

if [[ ! $@ =~ ^\-.+ ]]
then
    usage;
fi

while getopts m:d:t:f:l:h? OPT
do
    case $OPT in
        m) msg=$OPTARG;;
        d) date=$OPTARG;;
        t) time=$OPTARG;;
        f) dir=$OPTARG;; # [FIXED] 원본의 'd)'를 'f)'로 수정
        l) howMinute=$OPTARG;;
        h) help;;
        ?) help;;
    esac
done

echo "Arg msg: $msg"
echo "Arg date: $date"
echo "Arg time: $time"
echo "Arg directory: $dir"
echo "Arg howMinute: $howMinute"

### Analyze log from each AP by remote ssh

# [FIXED] AP1의 grep에 '-s' 옵션을 추가하여 다른 AP와 일관성 유지
# echo 'AP1 p7mesfab@172.25.4.17';
ap_summary=`ssh p7mesfab@172.25.4.17 grep "-sE '***** BPEL COMPLETED :: "${msg}"' "${dir}/*"" | grep -P "${date} ${time}" | grep -Po '(?<=Elapsed time = )\w+(?= miliseconds)' | awk 'BEGIN {min=999999;max=1} {if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {if(count>0) {print "AP1 count: "count" min: "min" max: "max" avg: "total/count}}'`

# echo 'AP1 p7mesfab@172.25.4.18';
ap_summary=$ap_summary"\n"`ssh p7mesfab@172.25.4.18 grep "-sE '***** BPEL COMPLETED :: "${msg}"' "${dir}/*"" | grep -P "${date} ${time}" | grep -Po '(?<=Elapsed time = )\w+(?= miliseconds)' | awk 'BEGIN {min=999999;max=1} {if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {if(count>0) {print "AP2 count: "count" min: "min" max: "max" avg: "total/count}}'`

# echo 'AP1 p7mesfab@172.25.4.19';
ap_summary=$ap_summary"\n"`ssh p7mesfab@172.25.4.19 grep "-sE '***** BPEL COMPLETED :: "${msg}"' "${dir}/*"" | grep -P "${date} ${time}" | grep -Po '(?<=Elapsed time = )\w+(?= miliseconds)' | awk 'BEGIN {min=999999;max=1} {if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {if(count>0) {print "AP3 count: "count" min: "min" max: "max" avg: "total/count}}'`

# echo 'AP1 p7mesfab@172.25.4.34';
ap_summary=$ap_summary"\n"`ssh p7mesfab@172.25.4.34 grep "-sE '***** BPEL COMPLETED :: "${msg}"' "${dir}/*"" | grep -P "${date} ${time}" | grep -Po '(?<=Elapsed time = )\w+(?= miliseconds)' | awk 'BEGIN {min=999999;max=1} {if($1>max) {max=$1}; if($1<min) {min=$1}; total+=$1; count+=1} END {if(count>0) {print "AP4 count: "count" min: "min" max: "max" avg: "total/count}}'`

ap_summar=`echo -e $ap_summary | grep "AP"`

### Show Analysis

echo
echo -e "$ap_summar" # [FIXED] 줄바꿈이 적용된 '$ap_summar' 변수로 수정
echo
if [ -z $howMinute ]; then
    # [FIXED] "Total Count: " 중복 오타 수정
    echo -e "$ap_summar" | awk 'BEGIN {min=99999;max=0} length($0) > 0 {total+=$3; if($5<min) {min=$5}; if($7>max) {max=$7}; count+=1; avg_sum+=$9} END {print "Total Count: "total", Min(ms): "min", Max(ms): "max", Avg(ms): "avg_sum/count}'
elif [ $howMinute -gt 0 ]; then
    echo -e "$ap_summar" | awk -v howMinute=$howMinute 'BEGIN {min=99999;max=0} length($0) > 0 {total+=$3; if($5<min) {min=$5}; if($7>max) {max=$7}; count+=1; avg_sum+=$9} END {print "Total Count: "total", Count/m: "total/howMinute", Count/s: "total/howMinute/60", Min(ms): "min", Max(ms): "max", Avg(ms): "avg_sum/count", Avg(s): "avg_sum/count/1000}'
fi
printLine
exit 0

사용 방법 예시

시간 Option에 정규식 입력 시, Back Slash를 사용하려면 Back Slash를 두 번 써야 하는 불편함이 있습니다.

마무리

이 스크립트를 활용하면 여러 서버의 로그를 확인하기 위해 반복적으로 접속하고 grep 명령을 실행하는 수고를 덜 수 있습니다. IP 주소나 grep 패턴을 환경에 맞게 수정하여 다양하게 활용해 보시기 바랍니다.


게시됨

카테고리

작성자