Script para testar o uso de memória [fechado]

2

Estou tentando colocar um band-aid provisório enquanto trabalho em uma solução para o vazamento de memória de um aplicativo. O que eu escrevi foi um pequeno script bash que eu coloquei na raiz no servidor. Isto é o que o script deve fazer:

  1. Obtenha o local em que é executado
  2. Verifique para ver se o script é o crontab
  3. Se não estiver no crontab, adicione ao crontab para executar a cada 5mins
  4. Teste a memória e verifique se o% está acima de percent_allowed
  5. Se o teste acima for reiniciado, reinicie o nginx & serviços 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

O teste de memória parece funcionar quando eu o executo, mas isso não parece estar funcionando.

Atualizar Eu precisava executar dos2unix no arquivo, mas também percebi que tenho um retorno sobre as condições de cada função no final ... de modo que isso não funcionaria. No momento, parece dizer que [[ na declaração if não foi encontrado.

Atualização 2 Parece próximo, ele está executando o reinício dos serviços, mas não está colocando o cron job em .. então eu não vejo isso rodando

#!/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

Está perto agora, acho que está sendo corrigido.

    
por jeremy.bass 21.09.2013 / 19:10

2 respostas

2

Para criar uma entrada crontab por meio de um script Bash, você precisará alterar esta linha:

*/5 * * * * $path/$cronfile

Para algo assim:

# 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

Você também pode se interessar e fazer tudo com esse forro:

cat <(crontab -l) <(echo "*/5 * * * $path/$cronfile") | crontab -

Seu script

Aqui está uma versão modificada do seu script que funciona para mim.

#!/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

Exemplo

$ ./memory_protect.sh 
/etc/init.d/nginx restart
/etc/init.d/php-fpm restart

$ crontab -l
*/5 * * * * /home/saml/tst/91789/memory_protect.sh

O script precisa ter essas duas linhas modificadas para que ele realmente reinicie os serviços nginx e php-fpm .

Altere estas linhas:         echo "/etc/init.d/nginx restart"         echo "/etc/init.d/php-fpm restart"

Para estes:

    /etc/init.d/nginx restart
    /etc/init.d/php-fpm restart

Eu fiz isso só para ver que o script estava sendo executado corretamente. OBSERVAÇÃO: se essas linhas de reinicialização devem ser prefixadas com sudo se esse script estiver sendo executado como qualquer outra que não seja root!

sudo /etc/init.d/nginx restart sudo /etc/init.d/php-fpm restart

Este uso provavelmente precisará ter NOPASSWD privileges pelo menos nesses 2 scripts, caso contrário, ele estará esperando que o usuário que possui o cron forneça uma senha.

A entrada do Crontab não existe?

Você encontrará este problema quando seu crontab não tiver sido criado ainda no diretório /var/sppol/cron . Você vai encontrá-lo quando você executar crontab -l assim:

$ crontab -l
no crontab for saml

Verificação dupla:

$ sudo ls -l /var/spool/cron/
total 0
-rw------- 1 root root 0 Sep 16 23:47 root

Então, basta fazer como se você fosse editá-lo e salvar o arquivo vazio para criá-lo:

$ 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!

Agora você deve ver isto:

$ crontab -l
$ 

E isso:

$ 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

Reiniciando os serviços

Outro problema que você enfrentará é se essa entrada do crontab estiver sendo executada como usuário, usuário1 e, em seguida, o usuário1 exigirá sudo de direitos para reiniciá-lo.

    
por 21.09.2013 / 19:51
2

Eu usaria monit para isso

Aqui está o exemplo do script monit, para sua exigência

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 

Tente reiniciar 5 vezes; se monit não puder reiniciar o servidor da web 5 vezes; apenas tempo limite para evitar condição de corrida.

Link de referência

    
por 21.09.2013 / 22:39