13

This is a follow-up to Memory limiting solutions for greedy applications that can crash OS?: ulimit and cgroups are not user friendly, and besides, wouldn't work with applications that spawn separate processes, such as Chrome/Chromium for each new (group of) tabs.

The simple and effective solution, used by Windows 7 actually, is to warn the user that the OS is running low on memory. This simple warning pop-up has prevented me from having any low-memory-caused system freeze in Windows, while I kept running into them on Ubuntu distros that I was testing live (where the RAM-mounted disk would eat up 2GB alone).

So, is there some way to automatically warn the user that the available RAM is nearing zero, without the user having to keep an eye on some memory monitoring gadget? Surely Conky could be configured to do that?

10

Check these scripts: Need application/script alerting when system memory is running out

#!/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();
?>
| improve this answer | |
  • 1
    The script works with small adaptations (I just used available=$(free -m | grep Mem | awk '{print $7}')). To make notify-send work with cron, refer to anmolsinghjaggi.wordpress.com/2016/05/11/… – morsch Aug 15 '16 at 21:50
  • If the language is not English, free will output localized text and parsing fails. Then add LANG=en_US.UTF-8 at the beginnning of the bash script. – Freddi Schiller May 19 '17 at 10:22
3

Another script that I wrote for this purpose:

#!/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
| improve this answer | |
2

Updated above script to also add details on top 3 memory-hungry processes. See at https://github.com/romanmelko/ubuntu-low-mem-popup

Here is the script itself:

#!/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
| improve this answer | |
  • Thank you for for contribution. The better practice here is to summarize (in this case copy) the content of the link you refer to. This way, your answer remains valid even if the link disappears. – Marc Vanhoomissen Mar 6 '19 at 14:07
1

Updated version of the script which works with 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
| improve this answer | |
1

Variant using RAM available, percentages and displays desktop notifications when called by cron (i.e. loop script doesn't have to be started after reboot):

#!/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
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.