OS : Red Hat Linux 7.2
Shell : bash
# 리눅스에서 top 을 이용해 백그라운드로 로깅을 남기기 위한 스크립트 입니다.
1. 스크립트에서 사용 하는 프로그램 설명
1.1 top
-n : 몇번 실행 할 것인지 동작 횟수를 지정 합니다.
-d : top 의 동작 인터벌을 지정 합니다.
-b : batch-mode 로 동작을 합니다.
ex) top -d 10 -n 100 -b
1.2 grep
-A : 몇번째 라인까지 출력 할것 인지를 지정
-v : 지정한 단어가 포함된 라인을 제외하고 출력
-e : 지정한 단어 패턴이 포함된 라인을 출력
--line-buffered : 출력된 라인을 버퍼에 저장
ex) ps -ef|grep -e "top -d"|grep -v "grep" , top -d 10 -n 100 -b |grep "load average" -A 15 --line-buffered
1.3 wc
-l : 총 라인 개수 출력
ex) ps -ef|grep -e "top -d"|grep -v "grep"|wc -l
2. 스크립트 동작 설명
2.1 스크립트 목적
- top 프로그램을 백그라운드로 동작을 시키면서 하루 단위로 로그파일을 남기기 위한 스크립트
2.2 스크립트 실행 방법
- 터미널이 종료 되도 실행 할 수있게 nohup 과 & 백그라운드 명령으로 스크립트를 실행
- loop_daily.sh [코드값] [interval val] [number_of_loops]
ex) nohup ./loop_daily.sh mon_cpu 10 9999999 &
2.3 스크립트 로그 확인 방법
[orcl:oracle@testdb] /home/oracle/DBA/script/mon> ls -lrt
total 23168
-rwxr--r-- 1 oracle dba 298 Jan 9 16:25 mon_start.sh
-rwxr--r-- 1 oracle dba 248 Jan 14 12:02 nohup_loop_daily.sh
-rw-r--r-- 1 oracle dba 0 Jan 15 13:29 loop_daily.log
-rw-r--r-- 1 oracle dba 4426481 Jan 16 00:01 mon_cpu_20200115.out
-rw-r--r-- 1 oracle dba 10096160 Jan 17 00:03 mon_cpu_20200116.out
-rwxr--r-- 1 oracle dba 2354 Jan 17 14:19 loop_daily.sh
-rwxr--r-- 1 oracle dba 642 Jan 17 14:21 test.sh
-rw-r--r-- 1 oracle dba 6955712 Jan 17 16:37 mon_cpu_20200117.out
[orcl:oracle@testdb] /home/oracle/DBA/script/mon> tail -30f mon_cpu_20200117.out
KiB Mem : 65768084 total, 3140312 free, 56665912 used, 5961860 buff/cache
KiB Swap: 33554428 total, 33491668 free, 62760 used. 6724120 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
39172 oracle -2 0 15.342g 15384 13000 S 1.4 0.0 326:53.18 ora_vktm_c+
44814 oracle -2 0 33.342g 15388 13000 S 1.4 0.0 265:32.01 ora_vktm_c+
49022 oracle 20 0 635716 41700 16712 S 0.9 0.1 791:05.24 gipcd.bin
49288 root 20 0 2650560 88364 25824 S 0.9 0.1 1230:48 crsd.bin
49380 oracle 20 0 1864148 58076 20440 S 0.9 0.1 1041:23 oraagent.b+
48906 root 20 0 1588876 59720 20180 S 0.8 0.1 530:56.96 orarootage+
49170 root 20 0 819476 34020 15904 S 0.7 0.1 965:23.83 octssd.bin
44878 oracle 20 0 33.342g 16440 13984 S 0.6 0.0 44:42.26 ora_mmnl_c+
49083 oracle rt 0 2375132 197012 90112 S 0.6 0.3 833:31.02 ocssd.bin
--
top - 16:37:36 up 136 days, 23:54, 4 users, load average: 1.08, 1.18, 1.21
Tasks: 766 total, 1 running, 765 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.9 us, 0.6 sy, 0.0 ni, 98.3 id, 0.2 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 65768084 total, 3138436 free, 56667824 used, 5961824 buff/cache
KiB Swap: 33554428 total, 33491668 free, 62760 used. 6722272 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
49272 root rt 0 1084448 122484 81072 S 2.2 0.2 1676:36 osysmond.b+
44814 oracle -2 0 33.342g 15388 13000 S 1.7 0.0 265:32.18 ora_vktm_c+
39172 oracle -2 0 15.342g 15384 13000 S 1.6 0.0 326:53.34 ora_vktm_c+
49212 oracle -2 0 1444824 15356 13164 S 1.1 0.0 1959:13 asm_vktm_++
48720 root 20 0 1884140 66064 19856 S 0.8 0.1 1310:17 ohasd.bin
49380 oracle 20 0 1864148 58076 20440 S 0.8 0.1 1041:23 oraagent.b+
48989 oracle 20 0 760336 35288 17024 S 0.7 0.1 927:40.69 evmd.bin
49288 root 20 0 2650560 88364 25824 S 0.7 0.1 1230:48 crsd.bin
49384 root 20 0 913932 31272 15096 S 0.7 0.0 888:09.65 orarootage+
^C
[orcl:oracle@testdb] /home/oracle/DBA/script/mon>
# 전체 스크립트
if [ $# -lt 1 ]; then
echo "usage: $0 sql_script [interval [number_of_loops]]"
echo " ex) nohup ./loop_daily.sh mon_cpu 10 9999999 &"
exit 1
fi
sql_script=$1
interval=${2:-10}
n_loops=${3:-999999999}
#round() {
# minor=${1#*.} # 소수자리만 남기고 지운다
# prc=$(( 10 ** ${#minor})) # 자리수 개수만큼 10의 제곱으로 구한다
# echo $( printf %.0f $( echo "scale=${#minor};(($prc*$1)+0.5)/$prc" | bc ))
#}
while true; do
if [ $n_loops -eq 0 ]; then
exit
fi
n_loops=`expr $n_loops - 1`
if [ $sql_script = "mon_cpu" ]; then
# 인터벌 시간 마다top 프로세스가 동작 중인지 확인
TOP_CHECK=`ps -ef|grep -e "top -d"|grep -v "grep"|wc -l`
# top 이 동작을 안하고 있으면 실행
if [ "$TOP_CHECK" == "0" ]; then
# 로그 파일 이름을 위한 날짜 값 저장
DATE=`date "+%Y%m%d"`
# 현재시간을 시, 분, 초 로 분리 해서 저장
HH24=`date "+%H"`
MM=`date "+%M"`
SS=`date "+%S"`
# Calcurate Time
# 변수의 수 값이 0 으로 시작 할 경우 8진 수로 인식 08 , 09 가 들어 오면 에러가 발생
# ex) test.sh: line 15: 59-08: value too great for base (error token is "08")
# 변수 앞에 10# 을 붙여 십진수로 인식 하게 함
# 24시 까지 남은 시간을 각 시간 단위 별로 계산
CH=$((23-10#$HH24))
CM=$((59-10#$MM))
CS=$((59-10#$SS))
# 위에서 나온 값을 초단위로 환산
remain_sec=$(((((10#$CH*60)+10#$CM)*60)+10#$CS))
# 24 hour repeat time, bash 숫자 연산은 정수로만 계산됨 소수점 계산을 위해선 awk , bc 를 이용
# 24시 까지 몇번의 인터벌이 필요한지 계산
repeat_time=$((($remain_sec/$interval)))
echo '---------------------------------------------------------------' >> ${sql_script}_${DATE}.out
echo ' ' >> ${sql_script}_${DATE}.out
top -d $interval -n $repeat_time -b |grep "load average" -A 15 --line-buffered >> ${sql_script}_${DATE}.out
sleep $interval
else
# top 이 실행 중이라면 인터벌 만큼 대기
sleep $interval
fi
else
exit
fi
done