{"id":187,"date":"2009-09-29T10:00:19","date_gmt":"2009-09-29T17:00:19","guid":{"rendered":"http:\/\/35.225.155.113\/blog\/index.php\/2009\/09\/29\/simple_remote_monitor_for_apache_with_perl\/"},"modified":"2019-10-13T13:14:53","modified_gmt":"2019-10-13T20:14:53","slug":"simple-remote-monitor-for-apache-with-perl","status":"publish","type":"post","link":"https:\/\/www.weinstein.org\/blog\/index.php\/2009\/09\/simple-remote-monitor-for-apache-with-perl.html","title":{"rendered":"Simple Remote Monitor for Apache with Perl"},"content":{"rendered":"<p>Sometime last week Apache on one of the<br \/>\nservers that manages some websites I host stop responding to<br \/>\nrequests, resulting in said websites being unavailable for a day and<br \/>\nhalf (or so). Unfortunately I didn&#8217;t know about the problem until<br \/>\nsomeone else notified me of the issue. Opps. Not good system<br \/>\nadministration that.<\/p>\n<p style=\"margin-bottom: 0in;\">\nThere are plenty of solutions for<br \/>\nmonitoring network services, but given that I&#8217;m just running Apache<br \/>\nfor a half dozen non-critical websites on the side, there&#8217;s no reason<br \/>\nto go overboard. Any sysadmin worth their weight in salt should be able<br \/>\nto whip something up with Perl in no time.<a class=\"sdfootnoteanc\" name=\"sdfootnote1anc\" href=\"#sdfootnote1sym\"><sup>1<\/sup><\/a><br \/>\nSo, what&#8217;s needed? Well, something that will remotely monitor the<br \/>\npool of websites and notify me if something is amiss:<\/p>\n<p><span class=\"mt-enclosure mt-enclosure-image\" style=\"display: inline;\"><img decoding=\"async\" loading=\"lazy\" alt=\"monitor_flow.jpg\" src=\"http:\/\/pdw.weinstein.org\/files\/monitor_flow.jpg\" class=\"mt-image-center\" style=\"margin: 0pt auto 20px; text-align: center; display: block;\" height=\"490\" width=\"337\"><\/span><\/p>\n<p>First up, making a simple HTTP GET request:<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre>my $url = \"http:\/\/$host\";\nmy $ua = LWP::UserAgent-&gt;new;\nmy $response = $ua-&gt;get( $url );\n<\/pre>\n<\/div>\n<p>Now we test the response, was it successful? If so, Apache returns an appropriate status code and the requested resource. If Apache is available, but unable to properly process the request it will responded with some relevant status code, which we wish to pass on for further troubleshooting:<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre>if ( !$response-&gt;is_success ) {\n# Do we have an error code?\nif ( $response-&gt;code ) {\nreportError(\"$host reports $response-&gt;message \\n\");\n} else {\n<\/pre>\n<\/div>\n<p>However a failed GET request will result in no status code since Apache probably failed to respond at all. In this case it would be helpful to determine if the issue is with Apache or something else. For that test a network ping is issued:<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre>\t\t# HTTP is down, is the network connection down too?\nmy $p = Net::Ping-&gt;new(\"icmp\");\nif ( $p-&gt;ping( $host, 2 )) {\nreportError (\"$host is responding,\nbut Apache is not.\\n\");\n} else {\nreportError (\"$host is unreachable.\\n\");\n}\n}\n<\/pre>\n<\/div>\n<p>Not too difficult that. Now, how do we go about communicating the issue at hand? SMS has always been my preferred method since my phone is usually close at hand and, iPhone or not, SMS is widely implemented and easy to use.<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre># Send SMS via cellular Email to SMS gateway\nmy ( $msg ) = @_;\nmy $to = \"7735551234\\@txt.att.net\";\nmy $from = \"pdw\\@weinstein.org\";\nmy $subject = \"Service Notification\";\nmy $sendmail = '\/usr\/lib\/sendmail';\nopen( MAIL, \"|$sendmail -oi -t\" );\nprint MAIL \"From: $from\\n\";\nprint MAIL \"To: $to\\n\";\nprint MAIL \"Subject: $subject\\n\\n\";\nprint MAIL $msg;\nclose( MAIL );\n<\/pre>\n<\/div>\n<p>All&#8217;s done? Not quite. For the fun of it, I figured broadcasting a message that the server was unavailable might be of use to regular visitors. What better way to broadcast a short message than via Twitter?<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre>my ( $msg ) = @_;\nmy $nt = Net::Twitter::Lite-&gt;new(\nusername =&gt; $username,\npassword =&gt; $password );\nmy $result = eval { $nt-&gt;update( $msg ) };\n<\/pre>\n<\/div>\n<p>Bring this all together, with cron gives us:<\/p>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre># monitor remote httpd servers every 30 minutes\n*\/30 * * * *   pdw  \/home\/pdw\/bin\/monitor.pl &gt;\/dev\/null 2&gt;&amp;1\n<\/pre>\n<\/div>\n<div style=\"padding: 5px; background-color: rgb(204, 204, 204);\">\n<pre>#!\/usr\/bin\/perl\nuse strict;\n\nuse LWP::UserAgent;\nuse Net::Ping;\nuse Net::Twitter::Lite;\n\nmy @hosts = ( \"pdw.weinstein.org\", \"www.weinstein.org\" );\n\nforeach my $host ( @hosts ) {\n\n\tmy $url = \"http:\/\/$host\";\n\tmy $ua = LWP::UserAgent-&gt;new;\n\tmy $response = $ua-&gt;get( $url );\n\n\tif ( !$response-&gt;is_success ) {\n\n\t\t# Do we have an error code?\n\t\tif ( $response-&gt;code ) {\n\n\t\t\treportError(\"$host reports\n\t\t\t$response-&gt;message.\\n\");\n\n\t\t} else {\n\n\t\t# HTTP is down, is the network connection down too?\n\t\tmy $p = Net::Ping-&gt;new(\"icmp\");\n\t\tif ( $p-&gt;ping( $host, 2 )) {\n\n\t\t\treportError ( \"$host is responding, \n\t\t\t     but Apache is not.\\n\" );\n\n\t\t} else {\n\n\t\t\treportError ( \"$host is unreachable.\\n\" );\n\n\t\t}\n\n\t}\n\n}\n\nsub reportError ($) {\n\n\tmy ( $msg ) = @_;\n\tmy $nt = Net::Twitter::Lite-&gt;new(\nusername =&gt; $username,\npassword =&gt; $pasword );\n\n\tmy $result = eval { $nt-&gt;update( $msg ) };\n\n\tif ( !$result ) {\n\n\t\t# Twitter has failed us,\n\t\t# need to get the word out still...\n\t\tsmsEmail ( $msg );\n\n\t}\n\n}\n\nsub smsEmail ($) {\n\n\tmy ( $msg ) = @_;\n\tmy $to = \"7735551234\\@txt.att.net\";\n\tmy $from = \"pdw\\@weinstein.org\";\n\tmy $subject = \"Service Notification\";\n\n\tmy $sendmail = '\/usr\/lib\/sendmail';\n\topen(MAIL, \"|$sendmail -oi -t\");\n\t\tprint MAIL \"From: $from\\n\";\n\t\tprint MAIL \"To: $to\\n\";\n\t\tprint MAIL \"Subject: $subject\\n\\n\";\n \t\tprint MAIL $msg;\n\tclose( MAIL );\n\n}\n<\/pre>\n<\/div>\n<hr>\n<div id=\"sdfootnote1\">\n<p class=\"sdfootnote\"><a class=\"sdfootnotesym\" name=\"sdfootnote1sym\" href=\"#sdfootnote1anc\">1<\/a> Of<br \/>\ncourse if I was worth my weight I would have had something in place<br \/>\nlong before it was called for&#8230;.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Sometime last week Apache on one of the servers that manages some websites I host stop responding to requests, resulting in said websites being unavailable for a day and half (or so). Unfortunately I didn&#8217;t know about the problem until someone else notified me of the issue. Opps. Not good system administration that. There are [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,92,82],"tags":[12,6,221,44,43,10,8,222,171],"_links":{"self":[{"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/187"}],"collection":[{"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=187"}],"version-history":[{"count":3,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/187\/revisions"}],"predecessor-version":[{"id":747,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/posts\/187\/revisions\/747"}],"wp:attachment":[{"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.weinstein.org\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}