6
\$\begingroup\$

Backstory

Recently, we've changed the PCs at my workplace to un Linux Mint.
It works amazing, is blazing fast and the adjustment time was very short.

However, I noticed my PC would freeze completely, sometimes.
I've determined that it is low RAM memory.

My working habits require me to open 10+ tabs (sometimes 100, in 5-8 Google Chrome windows).
This makes it so the swap is stuffed, as well as the RAM (Physical Memory).
Sometimes I have to use a VM running off of my PC, which takes 4GB for itself.

The code

Since old habits are hard to kill and isn't fun, I've decided to write code (which is a lot more fun).

Since Linux Mint doesn't warn about low available RAM, I've scattered around and put together a script to run every minute, and warn me when the memory is running low.

This script can also be executed from the console, displaying a message on it, if needed.
A detection method had to be added, since the output sent to cron is emailed by default.

#!/usr/bin/env bash
# based from https://askubuntu.com/questions/234292/warning-when-available-ram-approaches-zero
LANG=en_US.UTF-8

# gets available and total ram
RAM=$(free -m)
total=$(echo "$RAM"|awk '/^[mM]em\.?:/{print $2}')
available=$(echo "$RAM"|awk '/^[mM]em\.?:/{print $7}')

# warn if less than these levels is free
# warning = 20%
# critical = 10%
WARNING=$(expr $total / 5)
CRITICAL=$(expr $total / 10)

# -h int:transient:1 <-- don't store the notification
# https://unix.stackexchange.com/questions/393397/get-notify-send-to-clear-itself-from-notification-tray/401587
if [ $available -lt $CRITICAL ]; then
    # using -u critical doesn't allow the notification to go away after -t ms have past
    # this causes issues if afk, since the notifications will queue until the -u critical is closed
    notify-send -i error -h int:transient:1 -t 60000 "Low memory!" "$available/$total MB free, critical at $CRITICAL MB"
elif [ $available -lt $WARNING ]; then
    notify-send -h int:transient:1 -t 15000 "Memory is going low" "Available: $available/$total MB, warns at $WARNING MB"
fi

# outputs if not ran by cron
# https://unix.stackexchange.com/questions/46789/check-if-script-is-started-by-cron-rather-than-invoked-manually
if [ -t 0 ]; then
    echo "Available: $available/$total MB, warns at $WARNING MB, critical at $CRITICAL MB"
fi

This script runs in crontab -e, with the following:

# https://unix.stackexchange.com/questions/247860/notify-send-doesnt-work-at-cinnamon
DISPLAY=":0.0"
XAUTHORITY="/home/<username>/.Xauthority"
XDG_RUNTIME_DIR="/run/user/<output from id -u>"

* * * * * /usr/bin/env bash /home/<username>/<script-from-above>.sh

Conclusion

It was really hard to get to this point, with plenty of issues.
Most information was available online, but, making it work was a pain.

I'm not really good with Bash scripting, which probably means that I have some really bad mistakes.
As far as I know, it works as intended, when intended:

Notification

Besides that, is there anything I can improve or change?
Any optimization/optimisation I can do?
Any localization/localisation issues that may come?

\$\endgroup\$
  • 1
    \$\begingroup\$ Bravo for a large percentage of your code comments being StackExchange links. \$\endgroup\$ – chicks Sep 30 '18 at 14:55
  • \$\begingroup\$ Consider adding a couple gigabytes of swap space, it is a cheap solution nowadays. Easy to do in the form of an extra swapfile. Or Simply buy more ram, if you need it. \$\endgroup\$ – Michel Billaud Sep 30 '18 at 14:57
  • \$\begingroup\$ @MichelBillaud Well, even swap has a limit. To add swap, I would have to re-format the SSD (or mess with already-existing partitions) and that's a bigger pain that warning me that i have too much trash open. \$\endgroup\$ – Ismael Miguel Sep 30 '18 at 14:58
  • \$\begingroup\$ @chicks That's where I took most of the solutions I've found for my problems. I like to give credit where credit is due. \$\endgroup\$ – Ismael Miguel Sep 30 '18 at 15:00
  • \$\begingroup\$ @IsmaelMiguel with a swap FILE you don't have to change the partitions. \$\endgroup\$ – Michel Billaud Sep 30 '18 at 15:01
2
\$\begingroup\$

Kudos to you! This is a nice little script, easy to read and to understand. However, there is no reason to reach for expr. Most shells (including dash or even busybox sh) can interpret arithmetic expressions on their own:

WARNING=$(($total / 5))
CRITICAL=$(($total / 10))

Also, in [ ] expressions, I'd use quotes around variables, to make sure that they don't contain any spaces. In this case, we can be sure that they won't contain some, but it's still good practice to use them:

if [ "$available" -lt "$CRITICAL" ]; then
    ...
elif [ "$available" -lt "$WARNING" ]; then
    ...
fi

Other than that, I'd write the -u comment as a direct negative instead of a positive:

# Don't use `-u critical', as it will keep the notification even after -t ms
# and will cause notifications to queue up.

This comment still contains the same message: "don't use -u critical", but it's much more direct.

Since no bashism are used, we can even change the shebang to #!/bin/sh. By the way, some of those remarks where also found by ShellCheck, but it rightfully marks them as info level only.

\$\endgroup\$
  • \$\begingroup\$ Thank you! I completely forgot about ShellCheck! Been years since I've read that name. You actually made really good points and I find your version quite superior. The only thing I didn't really liked was the shortening of the question URLs. It is fine for sharing over email, IM or something that shows a preview. Otherwise, the link doesn't really say what it is for. Can you quickly say what unix.stackexchange.com/q/393397 is for? I can't. But if the only thing I have to say that's slightly negative is a comment, it means you have here a great answer. \$\endgroup\$ – Ismael Miguel Oct 24 '18 at 19:29
  • \$\begingroup\$ @IsmaelMiguel Thank you too. To be honest, the short URLs are a fragment of a general line-shortening process, as I also shortened the notify-send lines to 72 characters with \ , but then thought "that's personal preference, not necessarily style, although it would make it easier to read with less or vi on getty or similar". I reverted those changes but apparently forgot to revert the short links :| \$\endgroup\$ – Zeta Oct 25 '18 at 6:35
  • \$\begingroup\$ By the way, I also forget about ShellCheck all the time when I write my own scripts. I only remember it when I write a review, to be honest :) \$\endgroup\$ – Zeta Oct 25 '18 at 6:36
  • \$\begingroup\$ It's alright. I can apply the changes to the code without applying the short links. Also, you said to use quotes in the [ ] expressions, but you don't use it in the final version. I should start using ShellCheck more often as well. Another question, won't the command in the crontab change? \$\endgroup\$ – Ismael Miguel Oct 25 '18 at 8:46

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.