January 10, 2024

Quick server load monitor and alert

In crontab:

*/5 * * * * cat /proc/loadavg > /path/to/lafile.txt
1,6,11,16,21,26,31,36,41,46,51,56 * * * * wget -q -O - '[url:]lafile.php'

The loadavg command is thus run every 5 minutes, and the php file is run 1 minute later. The output of loadavg is a single line, eg:

0.75 0.35 0.25 1/25 1747

The 1st value is the average load over the past minute, the 2nd value over the past 5 minutes, and the 3rd over the past 15 minutes. (The 4th value is the number of currently running processes out of the total number of processes, and the last value is the ID of the last process used.)

The php file:

<?php
$loadavg = "";
if (file_exists('/path/to/lafile.txt')) {
   date_default_timezone_set('America/New_York');
   $latime = date("g:i:s a, d F Y", filemtime('/path/to/lafile.txt'));
   $loadavg = file_get_contents('/path/to/lafile.txt');
   preg_match('/(\d\.\d\d) (\d\.\d\d) (\d\.\d\d)/', $loadavg, $lamatch);
   if ( $lamatch[2] > 4 ) {
      require_once('/path/to/PHPMailer/PHPMailerAutoload.php');
      $mail = new PHPMailer();
      $mail->setFrom("[from@email]", "Sender");
      $mail->addAddress("to@email", "Recipient");
      $mail->Subject = "Server Load Alert";
      $mail->Body = $latime . ":\n\n 1-minute load average: " . $lamatch[1] . "\n 5-minute load average: " . $lamatch[2] . "\n15-minute load average: " . $lamatch[3];
      $mail->send();
   }
}

The php file gets the modification time and the first 3 values from file.txt, and if the 2nd value (ie, 5-minute load average) is more than the number of CPUs of the server (eg, 4), it sends an e-mail alert.

It may be possible to combine these into a single shell script with the use of awk, but I'm not familiar with it. Also, the mail() function instead of PHPMailer could be used.