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

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

[ Hits: 41.009 ]

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

Script de alteração do sources.list

Claro 3G no Ubuntu 8.04

Altera /etc/fstab colocando o parâmetro acl nas partições ext3.

Configurando IP, Nome de maquina, Gateway e Samba.

substituir strings nos nomes de arquivos


  

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

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts