Information Security Study

반복문으로 파일 내에 있는 모든 로그를 DB에 저장하기(시도중) 본문

네트워크 캠퍼스/3차 프로젝트

반복문으로 파일 내에 있는 모든 로그를 DB에 저장하기(시도중)

gayeon_ 2024. 8. 12. 17:21

반복문으로 파일 내에 있는 모든 로그를 DB에 저장하기(시도중)

log_aggr 디렉토리에 날짜별로 집계된 로그 파일을 db에 저장해볼 것이다.

 

 

 

우선 db 인스턴스를 생성했다.

 

 

 

3306 포트도 열어두었다.

 

 

 

인스턴스에 접속해서 root 계정의 비밀번호 설정을 해주었다.

 

 

 

사용할 유저를 생성하고 실습을 위해 우선 모든 권한을 부여했다.

권한 부여 후 적용을 위해 Flush privileges를 입력해야 한다.

 

select host, user form mysql.user where user = '유저명';

으로 유저의 권한을 확인할 수 있다.

%로 뜨는 것으로 보아 권한이 잘 부여되었다.

 

 

 

db 인스턴스에 root가 아닌 사용자로 접속한다.

 

 

 

데이터베이스를 생성하고 use해주었다.

 

 

 

위와 같은 구조로 sequence number, 데이터, 접속한 유저, 접속 엔드포인트를 저장할 수 있도록 테이블을 생성했다.

 

 

 

생성되었다.

 

 

/home/ubuntu/log/log-db.sh

집계된 로그 파일을 데이터베이스 스키마에 맞게 수정 후 별도의 디렉토리에 저장하는 스크립트

#!/bin/sh

# 1. 작업 경로 설정
aggr_dir="/home/ubuntu/log_aggr"
db_dir="/home/ubuntu/log_db"

# 작업 디렉토리 생성 (디렉토리가 없을 경우에만 생성)
mkdir -p "$aggr_dir"
mkdir -p "$db_dir"

# 2. 날짜별 파일명 설정
aggr_file="$aggr_dir"/$(date +%Y%m%d).log
db_file="$db_dir"/$(date +%Y%m%d)_for_db.log

# 3. 순번 초기화
count=1

# 4. 로그 파일 파싱 및 변환
# log_aggr 디렉토리에 있는 파일을 이용해 db 파일 생성
if [ -f "$aggr_file" ]; then
    while IFS= read -r line; do
        # 필요한 정보를 추출 (날짜/시간, 엔드포인트, 사용자)
        date=$(echo "$line" | awk '{print $2}')
        endpoint=$(echo "$line" | awk '{print $3}')
        user=$(echo "$line" | awk '{print $NF}')
        
        # 추출된 정보를 순번과 함께 원하는 형식으로 저장
        echo "$count    $date    $user    $endpoint" >> "$db_file"
        
        # 순번 증가
        count=$((count + 1))
    done < "$aggr_file"
    
    # 5. 작업 완료 메시지 출력
    echo "데이터베이스 파일 생성이 완료되었습니다. 생성된 파일: $db_file"
else
    echo "집계된 로그 파일($aggr_file)을 찾을 수 없습니다."
fi

 

db_dir은 집계된 로그 파일을 db 스키마에 맞게 수정한 후 저장될 경로다.

순번을 부여하기 위해 count를 선언했다.

 

 

# 4. 로그 파일 파싱 및 변환
# log_aggr 디렉토리에 있는 파일을 이용해 db 파일 생성
if [ -f "$aggr_file" ]; then
    while IFS= read -r line; do
        # 필요한 정보를 추출 (날짜/시간, 엔드포인트, 사용자)
        date=$(echo "$line" | awk '{print $2}')
        endpoint=$(echo "$line" | awk '{print $3}')
        user=$(echo "$line" | awk '{print $NF}')
        
        # 추출된 정보를 순번과 함께 원하는 형식으로 저장
        echo "$count    $date    $user    $endpoint" >> "$db_file"
        
        # 순번 증가
        count=$((count + 1))
    done < "$aggr_file"
    
    # 5. 작업 완료 메시지 출력
    echo "데이터베이스 파일 생성이 완료되었습니다. 생성된 파일: $db_file"
else
    echo "집계된 로그 파일($aggr_file)을 찾을 수 없습니다."
fi

 

집계 로그 파일이 존재하는지 확인한 후 

while IFS= read -r line로 집계 로그 파일을 한 줄씩 읽어들인다.

 

date=$(echo "$line" | awk '{print $2}')는 awk로 로그 파일의 두 번째 필드를 추출하여 date 변수에 저장한다.

endpoint와 user도 동일한 방식으로 변수에 저장한다.

 

echo "$count $date $user $endpoint" >> "$db_file" 은 추출된 정보를 순번과 함께 지정된 형식으로 db_file에 추가한다.

 

 

 

 

실행권한 부여 후 실행하면

 

 

 

생성되었다고 뜬다.

 

 

 

해당 디렉토리에서 파일을 확인하면 db 스키마에 맞게 저장되었다.

 

 

이제 log_db에 있는 로그 파일을 데이터베이스에 삽입하는 스크립트를 작성할 것이다.

 

 

/home/ubuntu/log/log-db-store.sh

#!/bin/bash

# MySQL 클라이언트 경로
MYSQL_CMD="/usr/bin/mysql"

# 데이터베이스 설정
DB_HOST="ip"
DB_USER="db 유저명"
DB_PASS="db 패스워드"
DB_NAME="db명"

# 로그 파일 경로 설정
db_dir="/home/ubuntu/log_db"
LOG_FILE="$db_dir/$(date +%Y%m%d)_for_db.log"
ERROR_LOG="/tmp/mysql_error.log"

# 로그 파일이 있는지 확인
if [ -f "$LOG_FILE" ]; then
    echo "로그 파일이 발견되었습니다: $LOG_FILE"

    # 로그 파일의 총 줄 수를 확인
    total_lines=$(wc -l < "$LOG_FILE")
    echo "로그 파일 총 줄 수: $total_lines"

    # 로그 파일을 한 줄씩 읽어서 처리
    while IFS='    ' read -r count logdate loguser logendpoint; do
        echo "처리 중 데이터: $count, $logdate, $loguser, $logendpoint"

        # loguser가 'null'일 경우 실제 SQL의 NULL로 변환
        if [ "$loguser" == "null" ]; then
            loguser="NULL"
        else
            loguser="'$loguser'"
        fi

        # 중복된 데이터가 있는지 확인
        DUPLICATE_CHECK=$(ssh ubuntu@$DB_HOST "$MYSQL_CMD -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -e \"SELECT COUNT(*) FROM a_log WHERE sequence_number='$count';\"" 2>&1 | tail -n 1)
        echo "중복 확인 결과: $DUPLICATE_CHECK" >> $ERROR_LOG

        if [ "$DUPLICATE_CHECK" -eq 0 ]; then
            # 데이터 삽입
            INSERT_RESULT=$(ssh ubuntu@$DB_HOST "$MYSQL_CMD -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -e \"INSERT INTO a_log (sequence_number, log_date, log_user, log_endpoint) VALUES ('$count', '$logdate', $loguser, '$logendpoint');\"" 2>&1)
            echo "삽입 결과: $INSERT_RESULT" >> $ERROR_LOG
            echo "데이터 삽입 완료: $count"
        else
            echo "중복된 데이터가 발견되었습니다: $count" >> $ERROR_LOG
        fi
    done < "$LOG_FILE"

    echo "로그 파일을 성공적으로 데이터베이스에 삽입했습니다."
else
    echo "로그 파일을 찾을 수 없습니다: $LOG_FILE"
fi

 

각 로그 항목에 대해 시퀀스 넘버로 중복인 로그 목록인지 확인하고

중복이 아닌 경우에만 데이터를 삽입하는 스크립트이다.

 

 

# 로그 파일이 있는지 확인
if [ -f "$LOG_FILE" ]; then
    echo "로그 파일이 발견되었습니다: $LOG_FILE"

 

로그 파일이 존재하는지 확인한다.

 

 

# 로그 파일의 총 줄 수를 확인
total_lines=$(wc -l < "$LOG_FILE")
echo "로그 파일 총 줄 수: $total_lines"

 

로그 파일의 총 줄 수를 출력해서 로그별로 줄바꿈이 되어있는지 확인한다.

 

 

# 로그 파일을 한 줄씩 읽어서 처리
while IFS='    ' read -r count logdate loguser logendpoint; do
    echo "처리 중 데이터: $count, $logdate, $loguser, $logendpoint"

 

로그 파일을 한 줄씩 읽고 공백을 기준으로 데이터를 분리해서 변수에 저장한다.

 

 

# 중복된 데이터가 있는지 확인
DUPLICATE_CHECK=$(ssh ubuntu@$DB_HOST "$MYSQL_CMD -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -e \"SELECT COUNT(*) FROM a_log WHERE sequence_number='$count';\"" 2>&1 | tail -n 1)
echo "중복 확인 결과: $DUPLICATE_CHECK" >> $ERROR_LOG

 

변수에 중복된 데이터가 있는지 확인하고 결과를 오류 로그에 기록한다.

 

 

if [ "$DUPLICATE_CHECK" -eq 0 ]; then
    # 데이터 삽입
    INSERT_RESULT=$(ssh ubuntu@$DB_HOST "$MYSQL_CMD -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -e \"INSERT INTO a_log (sequence_number, log_date, log_user, log_endpoint) VALUES ('$count', '$logdate', $loguser, '$logendpoint');\"" 2>&1)
    echo "삽입 결과: $INSERT_RESULT" >> $ERROR_LOG
    echo "데이터 삽입 완료: $count"
else
    echo "중복된 데이터가 발견되었습니다: $count" >> $ERROR_LOG
fi

 

중복 값이 없다면 데이터를 삽입한다.

 

 

 

실행했지만 로그 파일의 첫 행만 db에 저장되는 문제가 발생했다.