net-snmp + apcupsd


This script parses the output of the apcaccess command found in the apcupsd package, which provides an interface to serial or USB compatible APC UPSs. This script runs in concert with net-snmp to provide SNMP values for the following statistics (if they’re provided by the UPS)…

  • Battery Charge Percentage
  • Battery Time Remaining
  • Load Percentage
  • Low Transfer Voltage
  • Line Voltage
  • High Transfer Voltage
  • Battery Voltage
  • Nominal Battery Voltage


The following script does the heavy lifting…

#!/usr/bin/php -q

$regex = "/^(.+?)s*:(.*?)$/m";

$matchcount = preg_match_all($regex, $OUTPUT, $matches);

for ($x = 0; $x < count($matches[1]); $x++)
       $$matches[1][$x] = (float)trim($matches[2][$x]);

echo "$BCHARGE\n";
echo "$TIMELEFT\n";
echo "$LOADPCT\n";
echo "$LOTRANS\n";
echo "$LINEV\n";
echo "$HITRANS\n";
echo "$BATTV\n";
echo "$NOMBATT\n";

The following line should be placed in the snmpd.conf file to facilitate monitoring…

exec . APCUPSD /root/bin/digestapcupsd

The MIB number can be changed somewhat, but I’m not actually sure how much. This is just what I’m using.


If all works correctly, doing a snmpwalk to the specificed MIB should yield something similar to the following:

UCD-SNMP-MIB::ucdavis.60.1.1 = INTEGER: 1
UCD-SNMP-MIB::ucdavis.60.2.1 = STRING: "APCUPSD"
UCD-SNMP-MIB::ucdavis.60.3.1 = STRING: "/root/bin/digestapcupsd"
UCD-SNMP-MIB::ucdavis.60.100.1 = INTEGER: 0
UCD-SNMP-MIB::ucdavis.60.101.1 = STRING: "100"
UCD-SNMP-MIB::ucdavis.60.101.2 = STRING: "41"
UCD-SNMP-MIB::ucdavis.60.101.3 = STRING: "22"
UCD-SNMP-MIB::ucdavis.60.101.4 = STRING: "97"
UCD-SNMP-MIB::ucdavis.60.101.5 = STRING: "119"
UCD-SNMP-MIB::ucdavis.60.101.6 = STRING: "132"
UCD-SNMP-MIB::ucdavis.60.101.7 = STRING: "26.9"
UCD-SNMP-MIB::ucdavis.60.101.8 = STRING: "24"
UCD-SNMP-MIB::ucdavis.60.102.1 = INTEGER: 0
UCD-SNMP-MIB::ucdavis.60.103.1 = ""
  1. Hi,

    I was looking at trying this out but the PHP code looks incomplete? Any chance you can update it or email it to me?



    • There were a couple errors in the echo statements at the end from the pasting of the code into wordpress, but that’s the complete script. The errors have been corrected, by the way.

      • Thanks for the reply. Its still not working for me.

        I cant see where any of the variables you are echoing are assigned in the script. This is why I thought it wasn’t correct.

        Here is my output when I run it:

        " ./test.php
        PHP Notice: Undefined variable: BCHARGE in /tmp/test.php on line 14
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: TIMELEFT in /tmp/test.php on line 15
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: LOADPCT in /tmp/test.php on line 16
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: LOTRANS in /tmp/test.php on line 17
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: LINEV in /tmp/test.php on line 18
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: HITRANS in /tmp/test.php on line 19
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: BATTV in /tmp/test.php on line 20
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        PHP Notice: Undefined variable: NOMBATT in /tmp/test.php on line 21
        PHP Stack trace:
        PHP 1. {main}() /tmp/test.php:0

        Turning off notice errors prints several blank lines.

        If I print_r($matches) I can see the APC data is being extracted.

        PHP Version: PHP 5.3.10-1ubuntu3.8 with Suhosin-Patch (cli) (built: Sep 4 2013 20:05:42)

        • The double dollar sign “$$matches[1][$x]” is what should be handling the variable creation. Basically, that syntax should make a variable named with the contents of $matches[1][$x], so if that element in the matches array contained “FOO”, the $$matches[1][$x] syntax should give you a variable named $FOO.

          One thing that you might try is something the docs there suggested – using some curly braces to make sure things are being parsed correctly. Try changing “$$matches[1][$x]” to “${$matches[1][$x]}” and see if that helps.

  2. Thanks for the information. I got it working. For some reason the regex was ending up with a tab character after the variable name so when using $$ it was creating a variable with a tab at the end. I put a trim in before the assignment and it works.

    Thanks again!

  3. This worked for me:

    #!/usr/bin/php -q

    $regex = "/^(.+?)s*:(.*?)$/m";

    $matchcount = preg_match_all($regex, $OUTPUT, $matches);

    for ($x = 0; $x

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>