Smartmon tools



  • Hey everyone,
    I've been working on monitoring my harddisks via SMART and having the ability to view this info in the web interface.  I have come up with almost a complete working system right now, I think the only thing I'm missing is proper email functionality (you may get this from my last thread).  Lately I have not had a lot of time to work on this so I thought I'd post it up and see what everyone thinks.

    Instructions:
    login to your pf box either via SSH or consol login and go to a shell. 
    run "pkg_add -r smartmontools".
    copy the included code to a file called diag_smartmon.php and put that in "/usr/local/www/"
    access it in your web interface via https://your_router/diag_smartmon.php

    let me know what you think :D

    I will try to get the email thing working properly as soon as I can, unless somebody else does it first ;)

    Cheers
    -Eric

    
    #!/usr/local/bin/php
    // pkg_add -r smartmontools
    /*
        Smartmontools+ v1.00-000 - Copyright 2006, All rights reserved
        Created by Eric Friesen for pfSense
    */
    
    require("guiconfig.inc");
    
    $pgtitle = "Diagnostics: Smartmon Tools";
    $smartctl = "/usr/local/sbin/smartctl";
    $smartd = "/usr/local/sbin/smartd";
    $start_script = "/usr/local/etc/rc.d/smartd.sh";
    
    include("head.inc");
    ?>
    
    // Highlates the words "PASSED", "FAILED", and "WARNING".  
    function add_colors($string)
    {
        // To add words keep arrayes matched by numbers
        $patterns[0] = '/PASSED/';
        $patterns[1] = '/FAILED/';
        $patterns[2] = '/Warning/';
        $replacements[0] = '**PASSED**';
        $replacements[1] = '**FAILED**';
        $replacements[2] = 'Warning';
        ksort($patterns);
        ksort($replacements);
        return preg_replace($patterns, $replacements, $string);
    }
    
    // Edits smartd.conf file, adds or removes email for failed disk reporting
    function update_email($email)
    {
        // Did they pass an email?
        if(!empty($email))
        {
            // Put it in the smartd.conf file
            shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN -H -m " . $email . "/' /usr/local/etc/smartd.conf");
        }
        // Nope
        else
        {
            // Remove email flags in smartd.conf
            shell_exec("/usr/bin/sed -i old 's/^DEVICESCAN.*/DEVICESCAN/' /usr/local/etc/smartd.conf");
        }
    }
    
    function smartmonctl($action)
    {
        global $start_script;
        shell_exec($start_script . $action);
    }
    
    // What page, aka. action is being wanted
    // If they "get" a page but don't pass all arguments, smartctl will throw an error
    $action = (isset($_POST['action']) ? $_POST['action'] : $_GET['action']);
    switch($action)
    {
        // Testing devices
        case 'test':
        {
            $test = $_POST['testType'];
            $output = add_colors(shell_exec($smartctl . " -t " . $test . " /dev/" . $_POST['device']));
            echo '```
    ' . $output . '
    
    ```';
            break;
        }
    
        // Info on devices
        case 'info':
        {
            $type = $_POST['type'];
            $output = add_colors(shell_exec($smartctl . " -" . $type . " /dev/" . $_POST['device']));
            echo "```
    $output
    ```";
            break;
        }
    
        // View logs
        case 'logs':
        {
            $type = $_POST['type'];
            $output = add_colors(shell_exec($smartctl . " -l " . $type . " /dev/" . $_POST['device']));
            echo "```
    $output
    ```";
            break;
        }
    
        // Abort tests
        case 'abort':
        {
            $output = shell_exec($smartctl . " -X /dev/" . $_POST['device']);
            echo "```
    $output
    ```";
            break;
        }
    
        // Config changes, users email in xml config and write changes to smartd.conf
        case 'config':
        {
            if(isset($_POST['submit']))
            {
                // DOES NOT WORK YET...
                if($_POST['testemail'])
                {
    // FIXME                shell_exec($smartd . " -M test -m " . $config['system']['smartmonemail']);
                    $savemsg = "Email sent to " . $config['system']['smartmonemail'];
                    smartmonctl("stop");
                    smartmonctl("start");
                }
                else
                {
                    $config['system']['smartmonemail'] = $_POST['smartmonemail'];
                    write_config();
    
                    // Don't know what all this means, but it addes the config changed header when config is saved
                    $retval = 0;
                    config_lock();
                    if(stristr($retval, "error") <> true)
                        $savemsg = get_std_save_message($retval);
                    else
                        $savemsg = $retval;
                    config_unlock();
    
                    if($_POST['email'])
                    {
                        // Write the changes to the smartd.conf file
                        update_email($_POST['smartmonemail']);
                    }
    
                    // Send sig HUP to smartd, rereads the config file
                    shell_exec("/usr/bin/killall -HUP smartd");
                }
            }
            // Was the config changed? if so , print the message
            if ($savemsg) print_info_box($savemsg);
            // Get users email from the xml file
            $pconfig['smartmonemail'] = $config['system']['smartmonemail'];
    
            ?>
    
    | 
                                            $tab_array = array();
                        $tab_array[0] = array("Information/Tests", false, $_SERVER['PHP_SELF'] . "?action=default");
                        $tab_array[1] = array("Config", true, $_SERVER['PHP_SELF'] . "?action=config");
                        display_top_tabs($tab_array);
                    ?>
                     |
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="config">
    
    | Config |
    | Email Adress | 
    
                         |
    |   | 
    
                         |
    
            </form>
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="config">
    
    | Test email |
    |   | 
                            Send test email to 
                         |
    |   | 
    
                         |
    
            </form>
    
                    break;
        }
    
        // Default page, prints the forms to view info, test, etc...
        default:
        {
            // Get all AD* and DA* (IDE and SCSI) devices currently installed and stores them in the $devs array
            exec("ls /dev | grep '^[ad][da]*[0-9]$'", $devs);
            ?>
    
    **Note:** smartd will cause your disks to be spun up, thus overriding the Harddisk standby time in [System: Advanced](https://router/system_advanced.php).
    
    | 
                                            $tab_array = array();
                        $tab_array[0] = array("Information/Tests", true, $_SERVER['PHP_SELF']);
                        $tab_array[1] = array("Config", false, $_SERVER['PHP_SELF'] . "?action=config");
                        display_top_tabs($tab_array);
                    ?>
                     |
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="info">
    
    | Info |
    | Info type | 
                            Info
    
                            Health
    
                            SMART Capabilities
    
                            Attributes
    
                            All
    
                         |
    | Device: /dev/ | 
                            <select name="device">foreach($devs as $dev)                        {                            echo "<option value=" . $dev . ">" . $dev;                        }                        ?></option></select> 
                         |
    |   | 
    
                         |
    
            </form>
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="tests">
    
    | Perform Self Tests |
    | Test type | 
                            Offline
    
                            Short
    
                            Long
    
                            Conveyance (ATA Disks Only)
    
                         |
    | Device: /dev/ | 
                            <select name="device">foreach($devs as $dev)                        {                            echo "<option value=" . $dev . ">" . $dev;                        }                        ?></option></select> 
                         |
    |   | 
    
                         |
    
            </form>
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="logs">
    
    | View Logs |
    | Log type | 
                            Error
    
                            Self Test
    
                         |
    | Device: /dev/ | 
                            <select name="device">foreach($devs as $dev)                        {                            echo "<option value=" . $dev . ">" . $dev;                        }                        ?></option></select> 
                         |
    |   | 
    
                         |
    
            </form>
    
    <form action="<?= $_SERVER['PHP_SELF']?>" method="post" name="abort">
    
    | Abort tests |
    | Device: /dev/ | 
                            <select name="device">foreach($devs as $dev)                        {                            echo "<option value=" . $dev . ">" . $dev;                        }                        ?></option></select> 
                         |
    |   | 
    
                         |
    
            </form>
    
                    break;
        }
    }
    
    // print back button on pages
    if(isset($_POST['submit']) && $_POST['submit'] != "Save")
    {
        echo '
    [Back](' . $_SERVER['PHP_SELF'] . ')';
    }
    ?>
    
    **" . $ulmsg . "**\n"; ?>
    
    


  • Nice! Make that a package when you are done  :)


Locked