애플리케이션 메모리 누수에 대한 해결책을 찾는 동안 임시 반창고를 붙이려고 합니다. 내가 작성한 것은 작은 bash
스크립트로 서버의 루트 디렉터리에 위치합니다. 스크립트가 수행해야 하는 작업은 다음과 같습니다.
- 실행 중인 위치를 가져옵니다.
- 스크립트가 crontab인지 확인
- crontab에 없으면 crontab에 추가하여 5분마다 실행합니다.
- 메모리를 테스트하고 %가 Percentage_allowed보다 높은지 확인하세요.
- 위 테스트가 완료되면 nginx 및 php-fmp 서비스를 다시 시작하세요.
memory_protect.sh
:
#!/bin/sh
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=pwd #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
return [[ crontab -l | egrep -v '^$|^#' | grep -q $cronfile ]] && return 1 || return 0
}
test_memory(){
memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`
#if it's above 80% alert
return [[ $PERCENTAG>$percent_allowed ]] && return 1 || return 0
}
if [[ has_cron -eq 0 ]]
then
#was not here so add
#run this script every 5 mins
*/5 * * * $path/$cronfile
fi
if [[ test_memory ]]
then
#clear some memory
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
fi
메모리 테스트를 자체적으로 실행해 보면 잘 되는 것 같은데, 이건 안되는 것 같습니다.
고쳐 쓰다dos2unix
파일에서 실행 해야 하지만 결국에는 각 함수의 조건에 대한 반환이 발생한다는 것도 깨달았습니다. 따라서 이 방법은 작동하지 않습니다. 이제 해당 문을 찾을 수 없는 것 같습니다 [[
.if
업데이트 2 자세히 보면 서비스를 다시 시작하는 중이지만 cron 작업을 넣지 않아서 실행 중인 것이 보이지 않습니다.
#!/bin/bash
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=pwd #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
#return 0 #returning this just to test should
#be the next line but it's not working
return 0
[[ crontab -l | egrep -v '^$|^#' | grep -q $cronfile ]] && return 1 || return 0
}
test_memory(){
memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`
#if it's above 80% alert
[[ $PERCENTAG -gt $percent_allowed ]] && return 1 || return 0
}
if [[ has_cron -eq 0 ]]
then
#was not here so add
#run this script every 5 mins
#crontab -e */5 * * * $path/$cronfile
cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
else
echo "cron present"
fi
if [ test_memory ]
then
#clear some memory
sudo /etc/init.d/nginx restart
sudo /etc/init.d/php-fpm restart
fi
이제 거의 수정이 된 것 같아요.
답변1
Bash 스크립트를 통해 crontab 항목을 생성하려면 다음 줄을 변경해야 합니다.
*/5 * * * * $path/$cronfile
다음과 같은 경우:
# Write out current crontab
crontab -l > mycron
# Echo new cron into cron file
echo "*/5 * * * * $path/$cronfile" >> mycron
# Install new cron file
crontab mycron
rm mycron
이 라이너를 사용하여 모든 작업을 수행할 수도 있습니다.
cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
당신의 스크립트
다음은 나를 위해 일한 수정된 스크립트 버전입니다.
#!/bin/sh
cronfile=memory_protect.sh #NOTE THIS SHOULD DETECT IT'S SELF
path=$(pwd) #this is the path to the file
percent_allowed=80 #this should be max memory before action
has_cron(){
#is the file in the cron?
#return 0 #returning this just to test should
#be the next line but it's not working
if crontab -l | egrep -v '^$|^#' | grep -q $cronfile; then
return 1
else
return 0
fi
}
test_memory(){
memusage=$(top -n 1 -b | grep "Mem")
MAXMEM=$(echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}')
USEDMEM=$(echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}')
USEDMEM1=$(expr $USEDMEM \* 100)
PERCENTAGE=$(expr $USEDMEM1 / $MAXMEM)
#if it's above 80% alert
[[ $PERCENTAG>$percent_allowed ]] && return 1 || return 0
}
if has_cron;
then
#was not here so add
#run this script every 5 mins
#crontab -e */5 * * * $path/$cronfile
#cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -
crontab -l > mycron
# Echo new cron into cron file
echo "*/5 * * * * $path/$cronfile" >> mycron
# Install new cron file
crontab mycron
rm mycron
else
echo "cron present"
fi
if test_memory;
then
#clear some memory
echo "/etc/init.d/nginx restart"
echo "/etc/init.d/php-fpm restart"
fi
예
$ ./memory_protect.sh
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
$ crontab -l
*/5 * * * * /home/saml/tst/91789/memory_protect.sh
nginx
스크립트가 실제로 다시 시작 되고 서비스 되도록 하려면 이 두 줄을 수정해야 합니다 php-fpm
.
다음 줄을 변경하세요: echo "/etc/init.d/nginx restart" echo "/etc/init.d/php-fpm restart"
이것들을 위해:
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart
스크립트가 올바르게 실행되는지 확인하기 위해 이 작업을 수행합니다. 참고: sudo
이 스크립트를 루트가 아닌 다른 사용자로 실행하는 경우 이러한 다시 시작 줄 앞에 !
sudo /etc/init.d/nginx 재시작 sudo /etc/init.d/php-fpm 재시작
이를 사용하려면 NOPASSWD
두 스크립트 모두에 대한 최소한의 권한이 필요할 수 있습니다. 그렇지 않으면 cron을 소유한 사용자가 비밀번호를 제공할 때까지 기다립니다.
crontab 항목이 존재하지 않습니까?
crontab이 디렉토리에 생성되지 않은 경우 이 문제가 발생합니다 /var/sppol/cron
. 다음과 같이 실행 하면 이 문제가 발생합니다 crontab -l
.
$ crontab -l
no crontab for saml
다시 확인하세요:
$ sudo ls -l /var/spool/cron/
total 0
-rw------- 1 root root 0 Sep 16 23:47 root
따라서 간단히 편집하고 빈 파일을 저장하여 생성한다고 가정합니다.
$ crontab -e
# now you're in the vim editor, add a empty line
# type "i", hit return, hit Escape,
# and do a Shift + Z + Z to save!
이제 다음이 표시됩니다.
$ crontab -l
$
이:
$ sudo ls -l /var/spool/cron/
total 0
-rw------- 1 root root 0 Sep 16 23:47 root
-rw------- 1 saml root 0 Sep 21 16:20 saml
서비스 다시 시작
직면하게 될 또 다른 문제는 이 crontab 항목이 user1 사용자로 실행되는 경우 user1이 sudo
이를 다시 시작하려면 권한이 필요하다는 것입니다.
답변2
나는 사용할 것이다감시 장치이를 위해
귀하의 요구 사항에 대한 monit 스크립트 예는 다음과 같습니다.
check process nginx with pidfile /var/run/nginx.pid
start program = "/etc/init.d/nginx start"
stop program = "/etc/init.d/nginx stop"
if memory usage > 95% then restart
group www-data
if 5 restarts within 5 cycles then timeout
5번 다시 시작을 시도했습니다. 모니터가 실패하면 경합 상태를 피하기 위해 웹 서버를 5번 다시 시작했습니다.