simple backup (bash) script monitoring webpage

Do you also use mail to “report” back on succesfull bash backup scripts running all over your enterprise? The “Backup” mailbox is flushed each day ending up being deleted instead of being checked?

Well for all people in that situation I have written a very basic but functional “Monitoring” script written in PHP. It is not finished yet (needs refinement) and your free to extend it as you see fit.

What does it look like? (yes it needs to be graphical! )

How does it work?

  • copy the php scripts into an php enable webserver (wamp / apache & php / iis & php )
  • create a directory ‘data’ in the directory where the index.php is located.
  • call the script using any commandline webclient (example using wget (linux))
    Generate an post file containing the post data, this can be done in a script using some creativity😉
    echo “ok=hostname.domain.ext&msgs=all_backup_messages\n newline seperated” > ./post
    Use wget and the generated post file to call the script.
    wget -q –post-file ./post http://apache_php.hostname.ext/backup/index.php –output-document /dev/null
  • Logon to the backup script to view the state.

Possible calls?
index.php?ok=[hostname]
index.php?err=[hostname]
index.php?warn=[hostname]
index.php?debug=true
index.php?msgs=[all messages \n is translated to <br> automatically]

Example call
http://127.0.0.1/index.php?ok=localhost.localdomain.org&msgs=all accumilated messages \n new line messages \n finished..

The application exists out of following files…🙂

// Here is the sourcecode needed to get it all working🙂 //
// Please dont be too harsh, the code NEEDS MORE WORK //
// ITS CONSEPTUAL, BUT FUNCTIONAL. TIPS? PLZ POST //
// HINTS? PLZ POST, BASHING move on🙂 //

Good luck…

<?php
// Script by chris, written to track backup scripts over the network...
/////

include('subcsv.php');

// Global vars being declared.
$err = false;                   // We start without any errors (duh)
$errmsg = array();              // The error message array is empty
$datadir='./data/';     // Where do we store our reported data?
$view=false;                    // At first we dont want to view the data
// check if any of the required vars was used //
// If no instructions (gets) (registering) where send we simply show the
// recorded data. (reporting)
if(isset($_GET['ok']) || isset($_GET['warn']) || isset($_GET['err']) || isset($_POST['ok']) || isset($_POST['err']) || isset($_POST['warn'])){
        //////// CATCH A POTENTIAL OK ///////////
        if(isset($_POST['ok']) || isset($_GET['ok'])){
                if((strlen($_POST['ok']) > 3 ) || (strlen($_GET['ok']) > 3)){
                        $host['ok'] = (isset($_POST['ok'])) ? $_POST['ok'] : $_GET['ok'];
                }else{
                        $err = true;
                        $errmsg[] = 'Reported hostname to short!';
                }
        }else{
                $host['ok'] = false;
        }
        //////// CATCH A POTENTIAL WARN ///////////
        if(isset($_POST['warn']) || isset($_GET['warn'])){
                if((strlen($_POST['warn']) > 3 ) || (strlen($_GET['warn']) > 3)){
                        $host['warn'] = (isset($_POST['warn'])) ? $_POST['warn'] : $_GET['warn'];
                }else{
                        $err = true;
                        $errmsg[] = 'Reported hostname to short!';
                }
        }else{
                $host['warn'] = false;
        }
        //////// CATCH A POTENTIAL ERROR ///////////
        if(isset($_POST['err']) || isset($_GET['err'])){
                if((strlen($_POST['err']) > 3 ) || (strlen($_GET['err']) > 3)){
                        $host['ok'] = (isset($_POST['ok'])) ? $_POST['err'] : $_GET['err'];
                }else{
                        $err = true;
                        $errmsg[] = 'Reported hostname to short!';
                }
        }else{
                $host['error'] = false;
        }
        //////// VIEW Debugging? ///////////
        if(isset($_GET['debug'])){$debug = true;}else{$debug = false;}
}else{
        // if we have no instructions (gets) show the report.
        $view = true;
}
// CATCH POTENTIAL MESSAGE(S) (intended for the backup log😉 //
if(isset($_POST['msgs']) || isset($_GET['msgs'])){
        $msgs=(isset($_POST['msgs'])) ? $_POST['msgs'] : $_GET['msgs'];
}else{
        $msgs='';
}

// Start the functional part🙂 //
if(!$err){
        if($view){
                // Load the HTML header
                require_once('view_tmpl.php');
                // Fetch the files from the data dir
                // If any? //
                if($content = opendir($datadir)){
                        // Global counter
                        $gc = 1;
                        // Read the directory contents
                        while($item = readdir($content)){
                                if(strstr($item, '.bak' )){
                                        if(is_file($datadir.$item)){
                                                // Clear the data array
                                                $data = '';
                                                if($fp = fopen($datadir.$item, 'r')){
                                                        while($line = fgets($fp)){
                                                                $data[] = $line;
                                                                if($debug){print_r($data);}
                                                        }
                                                }else{
                                                        print('false');
                                                }
                                        }else{
                                                echo 'open failed?';
                                        }
                                        // how much entries does this backup have?
                                        $n = 0;
                                        $n = count($data);
                                        // find the last index
                                        $l = $n - 1;
                                        // restore the data
                                        $entities = str_getcsv_cust($data[0], ';');
                                        if($debug){var_dump($entities);}
                                        $first_backup = $entities[0][0];
                                        $entities = str_getcsv_cust($data[$l], ';');
                                        // Get the current days of year
                                        $cdate = getdate();
                                        // Compare the date of the last registration
                                        // with the current day of year.
                                        $fdate = getdate(strtotime($entities[0][0]));
                                        $diff = $cdate['yday'] - $fdate['yday'];
                                        // Validate entities[3] (reported status) //
                                        if($entities[0]['3'] == 'ok'){$c1="<td bgcolor='green'>{$entities[0]['4']}</td><td bgcolor='green'>{$entities[0]['3']}</td>";
                                        }elseif($entities[0]['3'] == 'err'){$c1="<td bgcolor='yellow'>{$entities[0]['4']}</td><td bgcolor='yellow'>{$entities[0]['3']}</td>";
                                        }else{$c1="<td bgcolor='red'>{$entities[0]['4']}</td><td bgcolor='red'>{$entities[0]['3']}</td>";}
                                        // Validate the date difference //
                                        if($diff > 1){
                                                $c2="<td bgcolor='red'>{$entities[0]['0']}</td>";
                                        }else{
                                                $c2="<td bgcolor='green'>{$entities[0]['0']}</td>";
                                        }
                                        // Convert the backup msg so the \n are converted to a readable message(s)
                                        $bmsg = nl2br($entities[0]['5']);
                                        $bmsg = str_replace('\n', '<br/>', $bmsg);
                                        $bmsg = str_replace('\r', '', $bmsg);
                                        // Print the validated row...
                                        print("<tr><td><div id='links'><a href='#'>$gc<span><table class='tooltip'width='100%' align='right' cellspacing='0'><tr><th>Backup messages</th></tr><tr><td><div align='left' style='padding-left:5px;'>$bmsg<br/><br/></div></td></tr></table></span></a></div></td>
                                                $c1$c2<td>{$entities[0]['1']}</td><td>$first_backup</td><td>$n</td></tr>");

                                        // Up the global counter🙂
                                        $gc++;
                                        #print($diff);
                                        #print_r($entities);
                                }
                        }
                }else{
                        print('no backups registered "YET"😉');
                }
        // Close the table //
        print('</table>');
        }else{
                // We are saving an backup state, register this request! //
                if(is_array($host)){
                        // Is this host allowed? //
                        include('allowed_hosts.php');
                                // Itterate through a single entry🙂
                        foreach($host as $k => $v){
                                // Collect some random but usefull information about this registration
                                $rip=$_SERVER['REMOTE_ADDR'];
                                $time=date('H:i:s');
                                $date=date('d-m-Y');
                                $file=$datadir.$v.".bak";
                                // Is this host allowed?
                                //if(in_array($v, $allowed_hosts)){
                                // Sometimes array indexes are predefined during script load, so filter these out🙂 //
                                        if(!empty($host[$k])){
                                                // If the file doesnt exist create it🙂 //
                                                if(!is_file($file)){
                                                        touch($file);
                                                }
                                                if($fp = fopen($file, 'a')){
                                                        $csv = "$date;$time;$rip;$k;$v;$msgs";
                                                        if(fwrite($fp, $csv)){
                                                                print('true <br>');
                                                                exit;
                                                        }else{
                                                                print('false');
                                                                exit;
                                                        }
                                                }
                                                // Debugging are we?
                                                if($debug){
                                                        print("$k > $v <br>\r\n");
                                                        print_r($msgs);
                                                }
                                        }
                                //}else{
                                //      print($_GET['ok']);
                                //      die('your host isnt allowed in the allowed_hosts yet!');
                                //}
                        }
                }else{
                        die('invalid instruction received!');
                }
        }
}else{
        print_r($errmsg);
}
?>
//SUBCSV.PHP
<?php
#if (!function_exists('str_getcsv')) {
    function str_getcsv_cust($input, $delimiter = ',', $enclosure = '"', $escape = '\\', $eol = '\n') {
        if (is_string($input) && !empty($input)) {
            $output = array();
            $tmp    = preg_split("/".$eol."/",$input);
            if (is_array($tmp) && !empty($tmp)) {
                while (list($line_num, $line) = each($tmp)) {
                    if (preg_match("/".$escape.$enclosure."/",$line)) {
                        while ($strlen = strlen($line)) {
                            $pos_delimiter       = strpos($line,$delimiter);
                            $pos_enclosure_start = strpos($line,$enclosure);
                            if (
                                is_int($pos_delimiter) && is_int($pos_enclosure_start)
                                && ($pos_enclosure_start < $pos_delimiter)
                                ) {
                                $enclosed_str = substr($line,1);
                                $pos_enclosure_end = strpos($enclosed_str,$enclosure);
                                $enclosed_str = substr($enclosed_str,0,$pos_enclosure_end);
                                $output[$line_num][] = $enclosed_str;
                                $offset = $pos_enclosure_end+3;
                            } else {
                                if (empty($pos_delimiter) && empty($pos_enclosure_start)) {
                                    $output[$line_num][] = substr($line,0);
                                    $offset = strlen($line);
                                } else {
                                    $output[$line_num][] = substr($line,0,$pos_delimiter);
                                    $offset = (
                                                !empty($pos_enclosure_start)
                                                && ($pos_enclosure_start < $pos_delimiter)
                                                )
                                                ?$pos_enclosure_start
                                                :$pos_delimiter+1;
                                }
                            }
                            $line = substr($line,$offset);
                        }
                    } else {
                        $line = preg_split("/".$delimiter."/",$line);

                        /*
                         * Validating against pesky extra line breaks creating false rows.
                         */
                        if (is_array($line) && !empty($line[0])) {
                            $output[$line_num] = $line;
                        }
                    }
                }
                return $output;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
#}

?>
// VIEW_TMPL.PHP
<?php
// File for the view html

// HEAD
print('
<!doctype html>
<html>
        <head>
                <meta http-equiv="refresh" content="30">
                <meta http-equiv="X-UA-Compatible" content="IE=8">
                <meta http-equiv="content-type" content="text/html; charset=UTF-8">
                <title>Backup status</title>
                <style>

                        table{
                        border-top:1px solid #000;
                        border-right:1px solid #000;
                        }

                        table th{
                        font-family:verdana;
                        font-size:12px;
                        font-weight:bold;
                        border-left:1px solid #000;
                        border-bottom:1px solid #000;
                        background-color:#CCC;
                        }

                        table td{
                        text-align:center;
                        font-family:verdana;
                        font-size:10px;
                        border-left:1px solid #000;
                        border-bottom:1px solid #000;
                        }

                        a:link{
                                display:block;
                                position:relative;
                                z-index:10;
                                height:100%;
                                width:100%;
                                text-decoration:none;
                        }

                        a:visited{
                                display:block;
                                position:relative;
                                z-index:10;
                                height:100%;
                                width:100%;
                                text-decoration:none;
                        }

                        div#links div{
                                position:static;
                                z-index:10;
                        }

                        div#links a:hover span {display: block;
                                position: absolute;
                                top: 0px;
                                left: 50px;
                                width: 700px;
                                padding: 5px;
                                margin: 10px;
                                z-index: 100;
                                color: #222;
                                background: #EEE;
                                font: 10px Verdana, sans-serif;
                                text-align: center;
                                border: 1px solid #000;
                        }

                        div#links a span {display: none;}

                        table tr:hover{
                                background-color:#CCC;
                                cursor:hand;
                        }

                        p{
                        font-family:verdana;
                        font-size:10px;
                        }

                        .tooltip table td{
                        align:left;
                        }
                </style>
        </head>
        <body>
');


// Start the Backup list
// Create a nice table
print('
        <table cellspacing="0" cellpadding="2" width="90%">
        <tr><td colspan="7"><p>insert a new backup by calling this script using the following url<br>
           '.$_SERVER['PHP_SELF'].'?{ok|err|warn}={hostname}&msgs={backup log \n seperated}<br/><br />
           download an example bash script <a href="/backup/download/">here<a/> </p></td></tr>
        <tr>
                <th>N</th>
                <th>Hostname</th>
                <th>State</th>
                <th>Date Last</th>
                <th>Time Last</th>
                <th>Date First Ever</th>
                <th># in file</th>
        </tr>');

?>

About Chris Gralike

Momenteel ben ik manager van de afdeling business continuity bij de zakelijke IT dienstverlener AMIS Services BV. Sinds 2003 ben ik actief in de ICT branche. Tussen 2003 en nu heb ik verschillende rollen vervuld. In de rollen: systeem- en netwerkbeheer, system engineer, servicemanager en nu practice manager ben ik in contact gekomen met uiteenlopende technologieën, methodologieën, ideeën, oplossingen en innovaties. Een rijke ervaring waarmee ik de klanten van Conclusion en AMIS elke dag probeer te ondersteunen. Mijn credo: 'Altijd opzoek een win-win tussen business en technologie.'

Posted on September 27, 2010, in Uncategorized. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: