Aviso quando a RAM disponível se aproxima de zero

13

Este é um acompanhamento de soluções de limitação de memória para aplicativos gananciosos que podem travar o SO? : ulimit e cgroups não são amigáveis ​​e, além disso, não funcionariam com aplicativos que geram processos separados, como Chrome / Chromium para cada nova (grupo de) guias.

A solução simples e eficaz, usada pelo Windows 7, na verdade, é avisar o usuário que o sistema operacional está com pouca memória. Esse pop-up de aviso simples me impediu de congelar o sistema com pouca memória no Windows, enquanto eu continuava correndo neles nas distros do Ubuntu que estava testando ao vivo (onde o disco montado na RAM consumia apenas 2 GB).

Portanto, existe alguma maneira de alertar automaticamente o usuário que a RAM disponível está chegando a zero, sem que o usuário tenha que ficar de olho em algum dispositivo de monitoramento de memória? Certamente Conky poderia ser configurado para fazer isso?

Dan Dascalescu
fonte
2
Quatro anos depois , parece que verificar periodicamente free -mé o caminho a percorrer.
Dan Dascalescu

Respostas:

8

Verifique estes scripts: Precisa de alertas no aplicativo / script quando a memória do sistema estiver acabando

#!/bin/bash

#Minimum available memory limit, MB
THRESHOLD=400

#Check time interval, sec
INTERVAL=30

while :
do

    free=$(free -m|awk '/^Mem:/{print $4}')
    buffers=$(free -m|awk '/^Mem:/{print $6}')
    cached=$(free -m|awk '/^Mem:/{print $7}')
    available=$(free -m | awk '/^-\/+/{print $4}')

    message="Free $free""MB"", buffers $buffers""MB"", cached $cached""MB"", available $available""MB"""

    if [ $available -lt $THRESHOLD ]
        then
        notify-send "Memory is running out!" "$message"
    fi

    echo $message

    sleep $INTERVAL

done

PHP:

#!/usr/bin/php
<?php
$alert_percent=($argc>1)?(int)$argv[1]:90;
//$interval=($argc>2):(int)$argv[2]:25;



//while(true)
//{
 exec("free",$free);

$free=implode(' ',$free);
preg_match_all("/(?<=\s)\d+/",$free,$match);

list($total_mem,$used_mem,$free_mem,$shared_mem,$buffered_mem,$cached_mem)=$match[0];

$used_mem-=($buffered_mem+$cached_mem);

$percent_used=(int)(($used_mem*100)/$total_mem);

if($percent_used>$alert_percent)
exec("notify-send 'Low Memory: $percent_used% used'");

//sleep($interval);
//}
exit();
?>
Especificação padrão
fonte
1
O script funciona com pequenas adaptações (eu acabei de usar available=$(free -m | grep Mem | awk '{print $7}')). Para fazer o envio de notificação funcionar com o cron, consulte anmolsinghjaggi.wordpress.com/2016/05/11/…
morsch
Se o idioma não for inglês, o free irá produzir texto localizado e a análise falhará. Em seguida, adicione LANG=en_US.UTF-8no início do script bash.
Freddi Schiller
2

Outro script que escrevi para esse fim:

#!/bin/bash
# Copyright 2019, Mikko Rantalainen
# License: MIT X License

# Minimum available memory until warning, default to 10% of total RAM (MiB)
THRESHOLD=$(grep "MemTotal:" /proc/meminfo | awk '{ printf "%d", 0.1*$2/1024}')
INTERVAL=60s

echo "Emitting a warning if less than $THRESHOLD MiB of RAM is available..."

while true; do
    meminfo=$(cat /proc/meminfo)
    free=$(echo "$meminfo" | grep "MemFree:" | awk '{ printf "%d", $2/1024}')
    available=$(echo "$meminfo" | grep "MemAvailable:" | awk '{ printf "%d", $2/1024}')
    inactive=$(echo "$meminfo" | grep "Inactive:" | awk '{ printf "%d", $2/1024}')
    reclaimable=$(echo "$meminfo" | grep "SReclaimable:" | awk '{ printf "%d", $2/1024}')
    usable=$(echo "$free + $inactive / 2 + $reclaimable / 2" | bc)
    if test -z "$available"; then
        message="Current kernel does not support MemAvailable in /proc/meminfo, aborting"
        notify-send "Error while monitoring low memory" "$message"
        echo "$message" 1>&2
        exit 1
    fi

    message="Available: $available MiB
Free: $free MiB
Maybe usable: $usable MiB"

    if [ "$available" -lt "$THRESHOLD" ]
        then
        notify-send -u critical "Low memory warning" "$message"
        echo "Low memory warning:"
    echo "$message"
    fi

    #echo "DEBUG: $message"
    sleep $INTERVAL
done
Mikko Rantalainen
fonte
Por que o por que notify-sendignora o parâmetro timeout : - / E por que não há documentação sobre o que são as categorias e os ícones de ações? Além disso, as novas linhas são ignoradas e a mensagem é truncada . -u criticalresolve isso.
Dan Dascalescu 13/02/19
Tecnicamente notify-send, não ignora o tempo limite. É o processo que recebe a observação como entrada e a exibe acima da área de trabalho que decide ignorar o tempo limite. Veja também: unix.stackexchange.com/q/251243/20336
Mikko Rantalainen
1

Versão atualizada do script que funciona com free from procps-ng 3.3.10

#!/bin/bash

#Minimum available memory limit, MB
THRESHOLD=400

#Check time interval, sec
INTERVAL=30

while :
do
    free_out=$(free -w -m)
    available=$(awk '/^Mem:/{print $8}' <<<$free_out)

    if (( $available < $THRESHOLD ))
        then
        notify-send -u critical "Memory is running out!" "Available memory is $available MiB"
        echo "Warning - available memory is $available MiB"    
    fi

    cat <<<$free_out
    sleep $INTERVAL
done
Jirka Hladky
fonte
1

Atualizado acima do script para também adicionar detalhes dos 3 principais processos que exigem muita memória. Veja em https://github.com/romanmelko/ubuntu-low-mem-popup

Aqui está o próprio script:

#!/usr/bin/env bash

set -o errexit
set -o pipefail
set -o nounset

# If the language is not English, free will output localized text and parsing fails
LANG=en_US.UTF-8

THRESHOLD=500
INTERVAL=300
POPUP_DELAY=999999

# sleep some time so the shell starts properly
sleep 60

while :
do
    available=$(free -mw | awk '/^Mem:/{print $8}')
    if [ $available -lt $THRESHOLD ]; then
        title="Low memory! $available MB available"
        message=$(top -bo %MEM -n 1 | grep -A 3 PID | awk '{print $(NF - 6) " \t" $(NF)}')
        # KDE Plasma notifier
        kdialog --title "$title" --passivepopup "$message" $POPUP_DELAY
        # use the following command if you are not using KDE Plasma, comment the line above and uncomment the line below
        # please note that timeout for notify-send is represented in milliseconds
        # notify-send -u critical "$title" "$message" -t $POPUP_DELAY
    fi
    sleep $INTERVAL
done
Roman Melko
fonte
Obrigado pela contribuição. A melhor prática aqui é resumir (neste caso, copiar) o conteúdo do link ao qual você se refere. Dessa forma, sua resposta permanece válida mesmo se o link desaparecer.
22619 Marc Marchohoississ
1

Variante usando RAM disponível , porcentagens e exibe notificações na área de trabalho quando chamadas pelo cron (ou seja, o script de loop não precisa ser iniciado após a reinicialização):

#!/usr/bin/env bash

# dbus env var required when called via cron:
eval "export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ | tr '\0' '\n')";

AVAIL_THRESHOLD=5

free_output=$(free)
mem_total=$(awk '/^Mem:/{print $2}' <<< $free_output)
mem_avail=$(awk '/^Mem:/{print $7}' <<< $free_output)
mem_avail_m=$(bc <<< "scale=1; $mem_avail/1024")
percent_avail=$(bc <<< "scale=1; $mem_avail*100 /$mem_total")
should_warn=$(bc <<< "$percent_avail < $AVAIL_THRESHOLD")

if (( $should_warn )); then
    notify-send "Memory warning - only $percent_avail% ($mem_avail_m MB) available"
else
    echo "Memory OK - $percent_avail% ($mem_avail_m MB) available"
fi
lambfrier
fonte