Profile picture

[Shell Script] 서버 관리 스크립트 (메모리 모니터링 / 리부팅 횟수 점검)

JaehyoJJAng2024년 05월 05일

▶︎ 메모리 점검

  • 전체 메모리에서 남는 free 메모리 용량이 12% 미만일 때, 도커 컨테이너 재시작

memory_container_restart.sh

#!/usr/bin/bash

CONTAINER_NAME="bdodb"
LOG_FILE="/var/log/$CONTAINER_NAME"

# Set the threshold for free memory percentage (12%)
THRESHOLD=12

TOTAL_MEMORY="$(free -m | awk '/Mem/{print $2}')"
FREE_MEMORY="$(free -m | awk '/Mem/{print $4}')"
TOTAL_MEMORY_GiB="$(free -g | awk '/Mem/{print $2}')"
FREE_MEMORY_GiB="$(free -m | awk '/Mem/{print $4}')"
CURRENT_TIME="$(date +"%H:%M:%S")"

# Calculate the free memory percentage
# RSS: 실제 점유하고 있는 물리 메모리 크기
FREE_PERCENTAGE="$(awk "BEGIN {printf \"%.2f\", $FREE_MEMORY / $TOTAL_MEMORY * 100}")"

# Calculate the total memoryt usage by mysqld GiB
MYSQLD_MEMORY=$(ps aux | grep 'mysqld' | grep -v 'grep' | awk '{sum += $6} END {printf "Total Memory Usage: %.2fGib\n", sum / (1024 * 1024)}')

exec 3>> "$LOG_FILE"
# Compare with the threshold
if (( $(echo "$FREE_PERCENTAGE < $THRESHOLD" | bc -l) ));
then
    echo "============" >&3
    echo "Current time: $CURRENT_TIME" >&3
    echo "Total memory is $TOTAL_MEMORY_GiB GiB" >&3
    echo "Free memory: $FREE_MEMORY_GiB GiB" >&3
    echo "Free percentage is $FREE_PERCENTAGE %" >&3
    echo "Mysqld memory usage: $MYSQLD_MEMORY MB" >&3
    echo "Free memory is below $THRESHOLD% of total." >&3
    echo "Mysqld was restarted due to insufficient memory." >&3
    echo "============" >&3
    echo " " >&3
    echo " " >&3

    # Execute the restart
    docker restart "$CONTAINER_NAME"
else
    echo "Free memory is above $THRESHOLD% of total." 
    echo "Total memory is $TOTAL_MEMORY_GiB GiB"
    echo "Free memory is $FREE_MEMORY_GiB GiB"
    echo "Free percentage is $FREE_PERCENTAGE %"
    echo "Apache memory usage is $APACHE_MEMORY"
fi
코드 설명
THRESHOLD=12 빈 메모리가 이 값(12%) 미만으로 떨어지면 MySQL 컨테이너를 재시작합니다.
TOTAL_MEMORY="$(free -m | awk '/Mem/{print $2}')" 시스템의 총 메모리를 MB 단위로 가져옵니다.
FREE_MEMORY="$(free -m | awk '/Mem/{print $4}')" 시스템의 사용 가능한 메모리를 MB 단위로 가져옵니다.
TOTAL_MEMORY_GiB="$(free -g | awk '/Mem/{print $2}')" 시스템의 총 메모리를 GB 단위로 가져옵니다.
FREE_MEMORY_GiB="$(free -m | awk '/Mem/{print $4}')" 시스템의 사용 가능한 메모리를 GB 단위로 가져옵니다.
CURRENT_TIME="$(date +"%H:%M:%S")" 현재 시간을 가져옵니다.
FREE_PERCENTAGE="$(awk "BEGIN {printf \"%.2f\", $FREE_MEMORY / $TOTAL_MEMORY * 100}")" 사용 가능한 메모리의 백분율을 계산합니다.
MYSQLD_MEMORY=$(ps aux | grep 'mysqld' | grep -v 'grep' | awk '{sum += $6} END {printf "Total Memory Usage: %.2fGib\n", sum / (1024 * 1024)}') MySQL 서버 프로세스의 메모리 사용량을 계산합니다.

‣ 실행 결과

해당 스크립트 실행

sudo bash memory_container_restart.sh

image


▶︎ 서버 리부팅 점검

  • 비정상적인 서버 리부팅 모니터링 점검을 위해 서버에서 발생하는 리부팅 횟수 확인
  • 스크립트 구조
    • last 명령어로 down (reboot)된 로그를 이용한 모니터링 진행
    • 생성한 스크립트를 rc.local에 등록하여 서버 부팅 시 스크립트 실행
    • 알람 전송 (디스코드, 텔레그램 ..)

reboot_check.sh

#!/usr/bin/bash

DISCORD_WEBHOOK_URI=""
host=$(hostname)

send_discord_notification() {
    payload=$(cat << EOF
    {
      "embeds": [{
          "title": "Alarm",
          "description": "$1",
          "color": "$2"
      }]
    }
EOF
    )
    curl -H "Content-Type: application/json" -X POST -d "$payload" "$DISCORD_WEBHOOK_URI"
}

b=$(last reboot | grep 'reboot' | wc -l)
up_time=$(cat /proc/uptime | awk '{print $1}' | cut -d . -f 1)

reboot_date=""
for i in $(seq $b)
do
    if [[ "$i" == 4 ]]; then
        break
    fi
    time=$(last -f /var/log/wtmp --fulltime |grep "system boot"| awk '{print $5, $6, $7, $8, $9}' | sed -n "${i}p")
    time_convert=$(date -d "$time" "+%Y-%m-%d %H:%M")
    reboot_date+="$time_convert\n"
    reboot_date_final=$(echo $reboot_date | sed 's/ /, /g')
done
echo $reboot_date
output="$host에서 총 $b회 리붓 되었습니다.\n\n**최근 리붓 시기**\n$reboot_date"

# 디스코드로 알림 전송
send_discord_notification "$output" "45973"
코드 설명
send_discord_notification() { ... } 이 함수는 디스코드로 메시지를 전송하는 역할을 합니다. 입력 매개변수로 메시지 내용과 색상을 받아서 디스코드 웹훅을 통해 해당 내용을 보냅니다.
b=$(last reboot | grep 'reboot' | wc -l) last reboot 명령어를 통해 시스템의 리부팅 로그를 확인하고, 이 중에서 'reboot'이라는 문자열을 가진 줄만 선택하여 총 리부팅 횟수를 세어 변수 b에 저장합니다.
up_time=$(cat /proc/uptime | awk '{print $1}' | cut -d . -f 1) /proc/uptime 파일을 통해 시스템의 켜진 시간(업타임)을 초 단위로 가져옵니다.
reboot_date="" 빈 문자열을 초기화하여 리부트 시간을 저장할 변수를 만듭니다.
for i in $(seq $b) 리부트 횟수만큼 반복하는 루프를 설정합니다.
time=$(last -f /var/log/wtmp --fulltime | grep "system boot" | awk '{print $5, $6, $7, $8, $9}' | sed -n "${i}p") /var/log/wtmp 파일에서 시스템 부팅 로그를 찾고, 각각의 부팅 시간을 저장합니다.
time_convert=$(date -d "$time" "+%Y-%m-%d %H:%M") 부팅 시간을 원하는 형식(년-월-일 시:분)으로 변환합니다.
reboot_date="$reboot_date $time_convert" 부팅 날짜를 변수 reboot_date에 추가합니다.
reboot_date_final=$(echo $reboot_date | sed 's/ /, /g') 부팅 날짜 사이에 쉼표를 추가하여 최종 부팅 날짜를 만듭니다.

‣ 실행 결과

해당 스크립트 실행

bash reboot_check.sh

image


‣ rc.local 등록

스크립트 등록

sudo vim /etc/rc.local

/etc/rc.local

#!/bin/bash

bash /home/dev/serverChecking/02_reboot_check.sh
exit 0

Loading script...