Node-Red Check Disk Usage

Using Node-Red to monitor disk usage

This is the second follow-up on my article series on Installing Node-Red as an intermediate layer between RFM interface and EmonCMS and Securing Node-Red as well as my use of this setup for a period of time. In this article I will tell you about how Node-Red can be used to monitor the system it is installed on, with focus on monitoring disk usage.

While Node-Red is great for handling the flows of data transmitted between Internet-of-Things devices, it can do more. Node-Red comes with some powerful nodes that enable a great deal of analytics and transformation of the received data, but some of the nodes can also be used for more trivial tasks, such as measuring free disk space or other system metrics and, e.g. tweeting any critical levels.

In my particular set up Node-Red is running on a Raspberry PI running the EmonHub (part of the EmonCMS Linux distribution), which only reserves very little space for the /var/log partition. This poses the problem that the partition gets filled up very quickly, which eventually causes the Raspberry PI to freeze.

The solution I have chosen to this problem utilises Node-Red’s exec node to run a script that checks the amount of space used on a given mount point. If it is below a given threshold nothing happens, but if it is above I get notified by e-mail about the situation allowing me to take action before the partition gets full. The script takes two arguments: first, the path to the mount point of the partition to monitor and second, the threshold at which the amount of used space is considered high:

#!/bin/bash

if [ $# != 2 ]; then
 exit 1
fi

path=$1
limit=$2

if [ "$path" == "" ]; then
 exit 2
fi

if [ "$limit" == "" ]; then
 exit 3
fi

used_space=$(df $path | awk 'NR==2 {print $5}')
let used_space=$(echo "$used_space" | sed 's/.$//')

echo '{"path": "'$1'", "percentage": '$used_space', "limit": '$limit'}'
exit 0

Note that the second argument is not actually used in the script, but is passed on along with the first argument and the percentage of disk space used to stdout in json format.

The output from the script (stdout) flows into a function node, which acts on the result of a comparison between the threshold and percentage of disk space used. If used disk space is above the threshold, an e-mail is sent to me, but only if an e-mail has not previously been sent under the same conditions. This ensures that I only receive one e-mail if disk usage on the given mount point remains high over several consecutive checks.

In practice this logic uses a flag in the context local to the function node. The flag is true when free disk space is low and false otherwise. An e-mail is sent only if the flag is set to true after having been false – in all consecutive checks with a positive outcome the flag will always have been true in advance. Because the script can be used to monitor disk space on several mount points, the flag variable is named after the given mount point (e.g. /var/log becomes path_varlog). The script is shown below:

var json=JSON.parse(msg.payload);
if (json.percentage > json.limit) {
 msg.payload="Disk usage on " + json.path + " is higher than " + json.limit + "%.";
 msg.from="from@here.com";
 
 //Only send one message!
 if (context["path_"+json.path.replace(/(\/)/g, "")] === true)
 return null;
 
 context["path_"+json.path.replace(/(\/)/g, "")] = true;
 return msg;
} else {
 context["path_"+json.path.replace(/(\/)/g, "")] = false;
 return null;
}

I have put both scripts in a sub-flow for re-use to monitor several mount points. The complete sub-flow can be imported using below export:

[{"id":"d8d7949b.272868", "type":"subflow", "name":"Disk usage", "in":[{"x":182, "y":302, "wires":[{"id":"34a54af6.0a577e"}]}], "out":[{"x":752, "y":289, "wires":[{"id":"869c1f50.ce67d", "port":0}]}, {"x":468, "y":302, "wires":[{"id":"34a54af6.0a577e", "port":1}]}]}, {"id":"34a54af6.0a577e", "type":"exec", "command":"/home/pi/.node-red/lib/scripts/check_disk_space.sh", "addpay":true, "append":"", "useSpawn":"", "name":"Disk usage", "x":325, "y":302, "z":"d8d7949b.272868", "wires":[["869c1f50.ce67d"], [], []]}, {"id":"869c1f50.ce67d", "type":"function", "name":"Disk usage vs. limit", "func":"var json=JSON.parse(msg.payload);\nif (json.percentage > json.limit) {\n    msg.payload=\"Disk usage on \" + json.path + \" is higher than \" + json.limit + \"%.\";\n    msg.from=\"from@here.com\";\n    \n    //Only send one message!\n    if (context[\"path_\"+json.path.replace(/(\\/)/g, \"\")] === true)\n        return null;\n    \n    context[\"path_\"+json.path.replace(/(\\/)/g, \"\")] = true;\n    return msg;\n} else {\n    context[\"path_\"+json.path.replace(/(\\/)/g, \"\")] = false;\n    return null;\n}", "outputs":"1", "noerr":0, "x":582, "y":289, "z":"d8d7949b.272868", "wires":[[]]}, {"id":"fc5f8ac3.03a078", "type":"subflow:d8d7949b.272868", "name":"Disk usage", "x":397.5, "y":288.5, "z":"22915660.dd6eaa", "wires":[["208cf2a.fdf730e", "4696dbc5.b96924"], ["208cf2a.fdf730e"]]}]


The sub-flow is triggered by an inject node, which runs every 30 minutes and sends the path of the mount point to monitor as payload to the sub-flow (which flows it to the script).

0 comments on “Using Node-Red to monitor disk usageAdd yours →

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: