Pular para o conteúdo

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

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.
Fernando phoemur
Hits: 41.827 Categoria: Shell Script Subcategoria: Avançado
  • Download
  • Nova versão
  • Indicar
  • Denunciar
O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

Descrição

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.
Download clearcache.sh Enviar nova versão
O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

Versões atualizadas deste script

Fernando

Versão 2 enviada 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

Fernando

Versão 3 enviada 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

euteste da silva

Versão 4 enviada 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
O Viva o Linux depende da receita de anúncios para se manter. Ative os cookies aqui para nos patrocinar.
Não conseguimos carregar os anúncios. Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.

checkip

Configuração de rede no Virtualbox

syncnow - sincronizar diretórios com servidor local

Abilitando impressora no cups automatico

Popular Mysql

#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:

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


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:

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;
}


Usando estas constantes:

MEM_MIN="1024";
MEM_LIVRE=`qmem Free`;
MEM_TOTAL=`qmem Total`;



E verificando;

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


e usando printf ao invés de echo;

    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));


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
#17 Comentário enviado por pphrep em 23/08/2016 - 07:50h
Parabéns pelo script... me ajudou muito.

Contribuir com comentário

Entre na sua conta para comentar.