Skip to content

Instantly share code, notes, and snippets.

@yrousse
Created March 27, 2017 10:58
Show Gist options
  • Save yrousse/b897048a03a3cf3380567214d118e69d to your computer and use it in GitHub Desktop.
Save yrousse/b897048a03a3cf3380567214d118e69d to your computer and use it in GitHub Desktop.
This script is meant to ping every 5 minutes some hosts and upon failure to respond, an appropriate alert will be sent via Pushover service
#!/usr/bin/perl
## Gentle Pushover script for CRON job
##
## This Perl script is meant to ping every 5 minutes a bunch of hosts
## and if some aren't responding, an appropriate alert will be sent via Pushover service
## https://pushover.net/
##
## Some behavior has been ironed out in order to check server status
## quietly but frequently while keeping Push alerts moderately intrusive and relevant.
##
## Check is done every 5 minutes, but alert is only sent when one
## or several hosts fail to reply to ping (then every hour as reminder (see $pushcycle)).
## Alert is also sent without waiting the one hour delay when any of the hosts
## has its status changed, then the script will fallback to its reminder role.
## Once all hosts are responding to ping, one last Alert will be sent
## (because it's good news!),
## then the script will go back into quiet mode (no more push).
##
## On the below code, replace values for @hosts, $token and $user declarations.
## See Pushover FAQ about adressing service APIs via Perl, here:
## https://pushover.net/faq#library-perl
## As an example, you can set your CRON job (crontab -e on Linux) as below:
## */5 * * * * perl /opt/gentlepushover.pl
use strict;
use warnings;
use Net::Ping;
use LWP::UserAgent;
my $p = Net::Ping->new("icmp");
my $ua = LWP::UserAgent->new();
my @hosts = ( "hostname.example.org","hostname.example.net","hostname2.example.org" );
my $APIurl = "https://api.pushover.net/1/messages.json";
my $token = "APP_TOKEN";
my $user = "USER_KEY";
my $timeout = 1;
my $file = "/tmp/pushover.tmp";
my $filehandle;
my $pushcycle = 12; # Because CRON is meant to be set to every 5 minutes, that makes one hour cycle.
my $verifiedhosts = "";
my $previousverifiedhosts = "";
my $wrongstatus = 0;
my $counter = 0;
foreach my $h (@hosts) {
pingv4($h);
}
readvariables();
if ($wrongstatus) {
$counter++;
if ($counter == 1
|| $counter > $pushcycle
|| $verifiedhosts ne $previousverifiedhosts) {
$counter = 1;
sendalert();
}
writevariables();
} else {
if ($counter > 0) {
$counter = 0;
sendalert();
writevariables();
}
}
$p->close();
close( $filehandle );
sub pingv4 {
my ($hostname) = @_;
if ($p->ping($hostname,$timeout)) {
$verifiedhosts = $verifiedhosts . "✔︎ " . $hostname . " ";
} else {
$wrongstatus = 1;
$verifiedhosts = $verifiedhosts . "✘︎ " . $hostname . " ";
}
}
sub readvariables {
if (-e $file) {
open $filehandle, "+<", $file or die "$! error while opening $file\n";
my $fh = <$filehandle>;
($counter,$previousverifiedhosts) = split("//",$fh);
} else {
open $filehandle, ">", $file or die "$! error while writing to $file\n";
writevariables();
}
}
sub writevariables {
seek( $filehandle, 0, 0 );
print $filehandle $counter . "//" . $verifiedhosts;
truncate $file,length($counter . "//" . $verifiedhosts);
}
sub sendalert {
my $req = $ua->post($APIurl, ["token" => $token, "user" => $user, "message" => $verifiedhosts,]);
}
@yrousse
Copy link
Author

yrousse commented Mar 27, 2017

Btw, if I missed something critical, please let me know… I'm currently not interested in learning Perl but I'm willing to keep this script in good shape.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment