Limpar o cache da memória RAM apenas quando necessário

Publicado por Fernando (última atualização em 27/05/2013)

[ Hits: 36.782 ]

Homepage: https://github.com/phoemur/

Download clearcache.sh

Download 1364849742.clearcache.sh (versão 2)

Download clearcache2.sh (versão 3)

Download 1369683997.clearcache.sh (versão 4)




Quando deixamos o servidor ligado por muitos dias é comum o uso excessivo da memória devido ao cache não usado.

Fiz este script que limpa o cache apenas quando a memória livre fica abaixo de determinado valor, assim posso deixar ele executando do cron a cada hora e ele só vai limpar o cache quando for realmente necessário (memória livre abaixo do que você definir).

Para limpar o cache usei:

# echo 3 > /proc/sys/vm/drop_caches

O que só funciona à partir do kernel 2.6.16.

  



Versões atualizadas deste script

Versão 2 - Enviado por Fernando em 01/04/2013

Changelog: Conforme sugestão dos colegas, troquei o grep pelo awk com menos comandos e acrescentei a possibilidade de loggar sempre que limpar o cache. Para isso achei melhor usar o logger, que é um utilitário do syslogd e que vai loggar no /var/log/messages.

Download 1364849742.clearcache.sh


Versão 3 - Enviado por Fernando em 08/05/2013

Changelog: Nesta nova versão eu implementei a função de daemon, desta forma a pessoa não precisa colocar no crontab, é só configurar e executar...

Tem diversas mudanças interessantes no código: daemon, controle de PID, cálculo floating point, controle de processos...

Uso:
--help :: Show this Help
--force :: Drop caches without checking
--start :: Run in daemon mode
--stop :: Stop the daemon
--restart :: Stop and restart daemon
--meminfo :: Only print memory information
(without arguments) :: Same as start

Download clearcache2.sh


Versão 4 - Enviado por euteste da silva em 27/05/2013

Changelog: Coloquei no script uma validação da versão do kernel, pois nem todos possuem essa feature.
E na function clear_cache estava dando problema a linha do if.

Download 1369683997.clearcache.sh


Esconder código-fonte

#!/bin/bash
#
#
# Este script limpa o Cache da Memória RAM sempre que a memória livre estiver abaixo de $MEM_MIN
# No caso deixei pra limpar o cache sempre que a memória livre estiver abaixo de 1GB, adaptar às suas necessidades
# Eu deixo este script no cron do root para executar a cada hora, e ele só vai limpar o cache quando for necessário
#
# Escrito por Fernando B. Giannasi - março/2013
#
# Referências: http://blog.philippklaus.de/2011/02/clear-cached-memory-on-ubuntu/
#              http://www.vivaolinux.com.br/dica/Limpando-a-memoria-cache-no-Linux


# Informações da memória
MEM_LIVRE=`cat /proc/meminfo | grep "^MemFree" | tr -s ' ' | cut -d ' ' -f2` && MEM_LIVRE=`echo "$MEM_LIVRE/1024.0" | bc`
MEM_TOTAL=`cat /proc/meminfo | grep "^MemTotal" | tr -s ' ' | cut -d ' ' -f2` && MEM_TOTAL=`echo "$MEM_TOTAL/1024.0" | bc`

MEM_MIN=`echo 1024`

# Só funciona como root, se não for root precisaremos usar o sudo
SUDO=`which sudo`
if [ "`whoami`" == "root" ]; then ROOT=true; fi
if [ ! "`which sudo`" ] && [ !$ROOT ]; then echo "Não é o superusuário e o SUDO não foi encontrado"; exit 1; fi


# Finalmente limpando o Cache...
if [ "$MEM_LIVRE" -le "$MEM_MIN" ]
then
    echo "Efetuando limpeza do Cache da memória..."
    if [ $ROOT ]; then sync; echo 3 > /proc/sys/vm/drop_caches; else $SUDO sync; echo 3 | $SUDO tee /proc/sys/vm/drop_caches > /dev/null; fi
    MEM_APOS=`cat /proc/meminfo | grep "^MemFree" | tr -s ' ' | cut -d ' ' -f2` && MEM_APOS=`echo "$MEM_APOS/1024.0" | bc`
    echo "Memória total instalada: $MEM_TOTAL MB"
    echo "Memória livre antes: $MEM_LIVRE MB"
    echo "Memória livre após: $MEM_APOS MB"

else
    echo "Não é necessário limpar o Cache da memória"
fi

exit 0

Scripts recomendados

Criando usuário com poderes de root

Controla Daemon do ProFTP

Velox + Ip Dinâmico

Enviar e-mail via shell script usando e-mail autenticado

SUED for Linux =]


  

Comentários
[1] Comentário enviado por removido em 26/03/2013 - 21:23h

Muito bom. Vou testar!

Teria como você sugerir como pode ser melhor usado no cron?

[2] Comentário enviado por hellnux em 27/03/2013 - 10:35h

Legal o script!

Deixar uma contribuição.

Em vez de (4 comandos):
cat /proc/meminfo | grep "^MemFree" | tr -s ' ' | cut -d ' ' -f2
Pode ser usado (2 comandos):
grep "^MemFree" /proc/meminfo | awk '{print $2}'

[3] Comentário enviado por removido em 27/03/2013 - 10:51h

Ainda tem essa outra sintaxe aqui:

awk '/^MemFree/ { print $2; }' /proc/meminfo

que substitui o grep

[4] Comentário enviado por phoemur em 27/03/2013 - 11:14h

Essa parte de regex realmente não é o meu forte... Obrigado pela contribuição...


No cron por exemplo podeira deixar assim:

#crontab -e

e colocar:
47 * * * * /usr/sbin/clearcache.sh (ou o local onde copiar o arquivo)

Assim ele vai executar aos 47 minutos de cada hora, agora acho que como é um script leve não deve ter problema executar em intervalo de tempo menor... Ele só vai tomar a ação de limpar o cache se a memória livre ficar baixa, abaixo de $MEM_MIN... Eu achei esta forma melhor do que colocar pra limpar o cache 1x/dia que é como o pessoal vinha fazendo...

abraços

[5] Comentário enviado por hellnux em 27/03/2013 - 14:24h

@Listeiro 037

Essa do awk não conhecia. Vivendo e aprendendo. Valeu!

[6] Comentário enviado por removido em 30/03/2013 - 00:11h


[4] Comentário enviado por phoemur em 27/03/2013 - 11:14h:

Essa parte de regex realmente não é o meu forte... Obrigado pela contribuição...


No cron por exemplo podeira deixar assim:

#crontab -e

e colocar:
47 * * * * /usr/sbin/clearcache.sh (ou o local onde copiar o arquivo)

Assim ele vai executar aos 47 minutos de cada hora, agora acho que como é um script leve não deve ter problema executar em intervalo de tempo menor... Ele só vai tomar a ação de limpar o cache se a memória livre ficar baixa, abaixo de $MEM_MIN... Eu achei esta forma melhor do que colocar pra limpar o cache 1x/dia que é como o pessoal vinha fazendo...

abraços


Valeu! Agora tenho uma ideia de quando é melhor dele ser executado.

[7] Comentário enviado por nofault em 01/04/2013 - 14:22h

echo "Memória total instalada: $MEM_TOTAL MB" >> /var/log/syslog
echo "Memória livre antes: $MEM_LIVRE MB" >> /var/log/syslog
echo "Memória livre após: $MEM_APOS MB" >> /var/log/syslog


seria interessante acrescentar um >> /var/log/syslog por exemplo assim ficaria no registro do sistema caso necessite consultar, no caso dos sistemas debian e derivados

[8] Comentário enviado por phoemur em 01/04/2013 - 18:00h

Postei uma nova versão trocando o grep pelo awk e adicionei a possibilidade de loggar utilizando um utilitário do syslogd chamado logger.

qualquer dúvida:

man logger

[9] Comentário enviado por removido em 07/04/2013 - 01:49h

Tenho uma observação sobre o uso de root no script:

[code]if [ "`id -u`" == "0" ];
then
echo "Only root does";
exit 1;
fi;[/code]

Se o usuário não tiver id de root, ele simplesmente sai antes de mais nada.
Essa avaliação pode ser feita bem no início.

[10] Comentário enviado por phoemur em 07/04/2013 - 13:29h

Legal cara, no início eu realmente deixei pra sair se não fosse o root, mas depois achei melhor chamar o SUDO quando não fosse root, da forma que está no script...

Quando ao id -u ou whoami acho que não faz muita diferença, a não ser que o usuário tenha mudado o usuário com UID 0 de root pra qualquer outra coisa...

Eu também tenho uma versão deste script que funciona como daemon e não precisa colocar no cron, seguindo essas idéias aqui:
http://www.vivaolinux.com.br/artigo/Daemons-com-shell-script?pagina=1

Basicamente um loop infinito com while, sleep pra dar o tempo e as funções start, stop, restart e status

Porém não postei porque o script de deixar no cron tem funcionado melhor...
Pro daemon ficar bom estou precisando ainda de dois arquivos, um pra ser o script e outro pra chamar no init, o rc.script... Se colocar tudo no mesmo arquivo ainda tenho percebido alguns bugs quando o arquivo tenta matar ele mesmo ou então fica com dois processos executando ao mesmo tempo... Ainda está em aperfeiçoamento.

[11] Comentário enviado por removido em 07/04/2013 - 22:35h

Beleza. A outra observação é um malabarismo usando awk e a criação de uma função:

[code]qmem () {
[[ "$1" == "Free" || "$1" == "Total" ]] || exit 1; # isso aqui pode ser transformado im if / then / else
COMM='/^Mem'"$1"'/ { printf "%d",$2/1024; }'
awk "$COMM" /proc/meminfo;
}[/code]

Usando estas constantes:

[code]MEM_MIN="1024";
MEM_LIVRE=`qmem Free`;
MEM_TOTAL=`qmem Total`;[/code]


E verificando;

[code]if [ $((MEM_LIVRE<=MEM_MIN)) ];
(...)[/code]

e usando printf ao invés de echo;

[code] MEM_APOS=`qmem Free`;
(...)
printf " Memória total instalada:\t%5d MB
Memória livre antes:\t%5d MB
Memória livre após:\t\t%5d MB\n
Memória livre liberada:\t%5d MB\n\n",$MEM_TOTAL,$MEM_LIVRE,$MEM_APOS,$((MEM_LIVRE-MEM_APOS));[/code]

Esse printf pode falhar por causa de indentação.

[12] Comentário enviado por tiekookeit em 10/04/2013 - 10:45h

Nice!

[13] Comentário enviado por phoemur em 11/05/2013 - 12:11h

A versão nova que eu postei (clearcache2.sh) não precisa mais do cron, funciona como daemon e é só configura e executar...

[14] Comentário enviado por oficinaiti em 07/08/2013 - 09:30h

Olá pessoal...

Baixe a Versão 4 do Script e encontrei um erro qto a validação da versão do Kernel ... Caso seu Kernel seja 3.0.0 por exemplo, o script irá falhar... qdo na verdade deveria seguir ok...

Reescrevi a parte de validação da versão do Kernel para:


# Validate kernel version
ENABLE_CACHE=$( echo $KERNEL | awk -F"." '{
if( ($1 >= 3) ){
print "1"
} else {
if( ($1 == 2) && ($2 >= 6) && ($3 >= 29) ){
print "1"
} else {
print "0"
}
}
}' )

Att
Rafael

[15] Comentário enviado por phoemur em 07/08/2013 - 11:20h

Na verdade já havia visto issoo faz algum tempo, porém como a versão 4 não foi eu quem publicou eu deixei pro colega atualizar, mas acho que ainda está errado... No meu pc deixei assim:

# Validade Kernel Version
if [ "$(awk '{print $3}' /proc/version | awk -F"." '{
if( ($1 == 2) && ($2 >= 6) && ($3 >= 29) || ($1 >= 3) ){
print "1"
} else {
print "0"
}
}' )" -ne "1" ]; then
echo "Current kernel cannot perform this action"
exit $E_GENERAL
fi

De qualquer forma obrigado pelo feedback

[16] Comentário enviado por limberger em 15/04/2015 - 13:37h

Pelo que pesquisei, limpar cache nunca ajuda... Só atrapalha!!!

http://www.linuxatemyram.com/


[17] Comentário enviado por pphrep em 23/08/2016 - 07:50h

Parabéns pelo script... me ajudou muito.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts