Network UPS Tools (NUT)

Your telephone switch is a pretty important piece of hardware so it is a good idea to power it with a UPS. This being the case, you may want to monitor it with the Network UPS Tools (NUT) package. This section tells you how to set up NUT and a UPS.

But, before we get on with setting up a UPS, the quick command to set the UPS battery date, after changing batteries is (note that /usr/local/ups/bin may just be /bin on some installations):

     /usr/local/ups/bin/upsrw -s battery.date=mm/dd/yy -u username -p password \
       upsname@localhost

This presupposes that the username and password are set in upsd.users and that "actions = set" are specified for the user. Also, upsd and the appropriate UPS driver must be up and running for the UPS in question.

Also, if you want to get rid of the "Change the battery" message and the red light on the UPS panel, you can force the battery test to be rerun immediately. However, before you do this, wait for three or four hours after the new battery is installed to give the UPS time to charge it first. Then, run the battery test, which will reset everything, if the new battery is OK. To do this, use:

     /usr/local/ups/bin/upscmd -u username -p password upsname@localhost \
       test.battery.start

The battery test should run (you'll see all of the messages it usually generates) for a few seconds and all will be well.

OK, having dispensed with the pleasantries, let's get on with the full installation of NUT. For some reason, in seems that CentOS does not supply a set of packages for NUT. Mind you, you don't have to take our word for it. You can try installing NUT by fetching and installing these packages:

     su
     yum install nut nut-client nut-cgi

If that doesn't work, we'll do the install the hard way. Start by fetching the latest release of NUT from http://www.networkupstools.org/. Unzip and untar the distro to a directory of your choice:

     mkdir /rpm/ups
     cp nut-2.2.1.tar.gz /rpm/ups
     cd /rpm/ups
     tar -xvzf nut-2.2.1.tar.gz

Create a new user, under which the UPS tools can run (otherwise they run as "nobody"). For example:

     /usr/sbin/useradd -c "UPS Monitoring Tools" -M -s /sbin/nologin ups

Add a directory where the UPS tools can store state information and make the new user the owner:

     su
     mkdir /var/state  (if necessary)
     mkdir /var/state/ups
     chown ups:ups /var/state/ups
     chmod u=rwx,g=rx,o= /var/state/ups

Change directory to the distribution directory and configure the build scripts:

     ./configure --with-user=ups --with-group=ups --sysconfdir=/etc/ups \
                 --mandir=/usr/share/man --with-cgi

Apply the patches for local source code changes or copy the local source code, if any, to the install directory before building. Currently, there are hacks to upsplot.pl, upsstats.c and upsmon.c (including upsmon.h). Put upsplot.pl in /etc/ups, after the "make install" is run (see below). Put the hacked ".c" and ".h" files in ./clients before doing the build.

Compile the source from the build directory, according to the INSTALL file and then install the build. Basically, you do the following, in the top level directory (but read the next two paragraphs first):

     make
     su
     make install

This should put most things in:

     /etc/ups
     /usr/local/ups/bin
     /usr/local/ups/sbin
     /usr/share/man

If you receive errors about "gd" during configure, go get it and install it before continuing. On some systems, you can do:

     su
     yum install gd gd-devel php-gd

Otherwise, you can get the source here:

     http://www.libgd.org/

In the event that you need libpng or zlib in order to compile gd, they can be found at these URLs:

     http://www.libpng.org/pub/png/pngcode.html
     http://www.gzip.org/zlib/

Also, if you're going to be using upsplot.pl, you will need to make sure that GD.pm is available. If not, you should install it from CPAN:

     perl -MCPAN -e shell
     install GD

Hack the udev rules for the tty device, that the UPS will be connected to, to give permissions to the ups user. These can be found in the /etc/udev/rules.d dirctory, typically in the file /etc/udev/rules.d/50-udev.rules. Add something to the effect of:

     # Special case for the UPS devices.
     KERNEL=="ttyS2",                NAME="%k", GROUP="ups", MODE="0660",
                                     OPTIONS="last_rule"

Add these lines before the general case rules for the tty devices.

Alternately, the best place to add your udev rules for NUT is in a separate rules file that you make up just for this purpose (that way, subsequent releases of NUT or the OS won't monkey with your rules for the serial port). We suggest calling the file "52_nut-ttyups.rules. It should be created in the /etc/udev/rules.d directory. You should add something like the following to that file, depending on which serial port you need to use:

     # udev rules for NUT serial drivers
     # Special case for the UPS devices
     KERNEL=="ttyS1", group="ups", MODE="0660"

/etc/ups/ups.conf:

Copy the file ups.conf.sample and hack it to set up the machine/UPS configuration, per the instructions in the INSTALL file. For an APC SmartUPS, the following config information applies:

     [bevatron]
          driver = apcsmart
          port = /dev/ttyS0

/etc/ups/upsd.conf:

On older versions of NUT, copy the file upsd.conf.sample. It is probably OK as is but, if you'd like to be able to monitor this machine's UPS from your home network, add something like:

     ACL homeworld 192.168.1.0/24
     ACCESS grant monitor homeworld

Or, if you don't want to be messing about and you want to be able to do anything from the local network (e.g. run battery tests), try replacing the existing rules with:

     ACL all 0.0.0.0/0
     ACL localhost 127.0.0.1/32
     ACL homeworld 192.168.1.0/24
     ACCEPT homeworld
     ACCEPT localhost
     REJECT all

On newer versions of NUT (e.g. version 2.4), copy the upsd.conf.sample file and replace the LISTEN directives with:

     LISTEN 127.0.0.1
     LISTEN 192.168.1.123 3493

You should use the actual IP address of the machine where NUT is being installed in place of 192.168.1.123 (above). If the machine has two or more NICs and you want NUT to listen on all of them, add additional LISTEN directives for the IP address of each of them.

Note that, if you have an older config file and are upgrading to a newer version of NUT, you will need to remove all of the ACL, ACCEPT and REJECT rules and simply use LISTEN. Apparently, the designers have decided that NUT should get out of the security business and leave everything to the firewall. Consequently, the rules are no longer accepted and LISTEN is simply used to tell NUT which port to listen on.

/etc/ups/upsd.users:

Copy the file upsd.users.sample. Add a user that will allow upsmon on the local host to shut down the machine if the power goes south as well as do periodic battery tests:

     [lmmonitor]
         password = ItsASecret
         allowfrom = localhost
         instcmds = test.battery.start
         actions = set
         upsmon master

/etc/ups/upsmon.conf:

Copy the file upsmon.conf.sample. Change the group ownership to the ups user and give it group permissions:

     chgrp ups /etc/ups/upsmon.conf
     chmod g+rw /etc/ups/upsmon.conf

Make the following changes to the file to begin monitoring the UPS:

     NOTIFYCMD /etc/ups/notify
     RUN_AS_USER ups
     MONITOR bevatron@localhost 1 lmmonitor ItsASecret master
     NOTIFYFLAG COMMBAD  SYSLOG+EXEC
     NOTIFYFLAG COMMOK   SYSLOG+EXEC
     NOTIFYFLAG FSD      SYSLOG+EXEC
     NOTIFYFLAG LOWBATT  SYSLOG+EXEC
     NOTIFYFLAG NOCOMM   SYSLOG+EXEC
     NOTIFYFLAG ONBATT   SYSLOG+WALL+EXEC
     NOTIFYFLAG ONLINE   SYSLOG+WALL+EXEC
     NOTIFYFLAG REPLBATT SYSLOG+EXEC
     NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
     NOTIFYFLAG OVERTEMP SYSLOG+EXEC

If you want to monitor UPS temperature and you've applied the proper hacks (or the temperature hacks are included in your version of the source), add the following:

     # --------------------------------------------------------------------------
     # UPSOVERTEMP - Temperature (in Celcius) which is too high for operation
     #
     # upsmon will check all UPS that return temperature information against this
     # value.  If the UPS temperature exceeds this value, an OVERTEMP notification
     # will be generated.
     #
     # Note that certain UPS are renown for cooking and even burning up batteries
     # (some reports of spectacular battery fires have been received).  From
     # actual observed log data, it appears that prior to burning up the
     # batteries, the UPS internal temperature rises significantly.  Hence,
     # monitoring the UPS temperature can be a valuable tool towards detecting
     # battery cooking, before the UPS burns the place down (the UPS is supposed
     # to solve problems, not cause them, isn't it).
     #
     # Once again, typical observed internal temperatures are in the 40 to 50
     # degree Celcius range.  Observed temperatures of 80 degrees Celcius prior
     # to an actual battery failure are indicative of pending failure.  Thus, to
     # be safe, the the UPSOVERTEMP value should be set in the 60-70 degree
     # range.
     UPSOVERTEMP 60.0

/etc/sysconfig/upsd:

If you use any of the following scripts, you will need to either create or update /etc/sysconfig/upsd. This file contains the options that tell the UPS scripts which UPS boxes to monitor, what to do about logging, etc. Here is an example that can be used for a standalone Asterisk system:

     #
     # Configuration for the NUT UPS monitoring and power down daemons.
     #
     # The list of UPS boxes to be controlled are set by UPS_BOXES, for example:
     #
     #      "My_UPS"
     #      "UPS-1 UPS-2"
     #
     # For clustering support, the list of UPS boxes on the primary server is set
     # by UPS_BOXES_PRIMARY and the list of UPS boxes on the secondary server is
     # set by UPS_BOXES_SECONDARY.
     #
     # You may define all three parameters in this config file and the startup
     # script will choose the appropriate one, based on whether clustering is
     # enabled and, if so, which role the server is playing.
     #
     UPS_BOXES="bevatron"
     UPS_BOXES_PRIMARY=""
     UPS_BOXES_SECONDARY=""
     #
     # If you would like to start logging of UPS statistics at regular intervals
     # to a log file too, define the location of the log file and the logging
     # interval.  Otherwise, if the LOG_PATH is set to an empty string, the
     # logging daemon isn't started.
     #
     # A separate file is created for each UPS that is monitored.  The name of the
     # file is created by appending the UPS name to the LOG_PATH value, separated
     # by a period.  For example:
     #
     #      LOG_PATH="/var/log/upslog"
     #      UPS_BOXES="UPS1 UPS1"
     #
     #      Log files = /var/log/upslog.UPS1, /var/log/upslog.UPS2
     #
     # The log interval is given in seconds by LOG_INTERVAL.
     #
     # The group that will be used to create log files is set by UPS_GROUP.  You
     # may find it useful to have your logfiles set to a different group and
     # given read/write permissions so that they can be accessed by UPS users.
     # Otherwise, root permissions are used.
     #
     LOG_PATH="/var/log/upslog"
     LOG_INTERVAL=30
     UPS_GROUP="ups"
     #
     # For secondary and/or standalone servers, if you'd like the UPS logs to be
     # copied to the primary server for consolidation purposes, define the
     # server's name here and the logging directory where they will be copied to.
     #
     # PRI_SERVER="jump-gate"
     # PRI_LOG_PATH="/var/log/upslog"

While we're at it, we'd like the logfiles to be created with the correct permissions, so let's create an empty one for each UPS before we proceed any further. Logrotate will take care of this when it rotates the log files but let's start with:

     su
     touch /var/log/upslog.bevatron
     chgrp ups /var/log/upslog.bevatron
     chmod g+w /var/log/upslog.bevatron

/etc/ups/batterytest:

Set up a script that will test a UPS' battery at regular intervals. This script can be scheduled from crontab:

     #! /bin/sh
     #
     # batterytest - Script to test the battery of a UPS at regular intervals.
     #
     # This script is used by cron to periodically test the battery of a UPS.
     #
     #
     # Define the install path for the UPS binaries.
     #
     INSTALL_PATH="/usr/local/ups"
     #
     # Source the UPS configuration.
     #
     if [ -f /etc/sysconfig/upsd ]; then
        . /etc/sysconfig/upsd
     fi
     #
     # Source the clustering configuration.
     #
     if [ -f /etc/sysconfig/clustering ] ; then
         . /etc/sysconfig/clustering
     else
         SERVERROLE=Standalone
     fi
     if [ x"$SERVERROLE" == x ]; then
         SERVERROLE=Standalone
     fi
     #
     # Determine which UPS boxes we can test.
     #
     if [ ${SERVERROLE} = "Primary" ] ; then
         UPS_BOXES=$UPS_BOXES_PRIMARY
     else
         if [ ${SERVERROLE} = "Secondary" ] ; then
             UPS_BOXES=$UPS_BOXES_SECONDARY
         fi
     fi
     #
     # For all of the UPS on this system, see which one we're testing.
     #
     for UPSBox in $UPS_BOXES; do
      if [ x"$UPSBox" == x"$1" ]; then
          $INSTALL_PATH/bin/upscmd -u jgmonitor -p ItsASecret \
              ${1}@localhost test.battery.start
      fi
     done

Change the permissions of the script, after you create it, to add execute permission:

     su
     chmod ugo+x /etc/ups/batterytest

/etc/ups/notify:

Create the following script to send event notifications to root, via email, whenever the UPS has something important to say. Note that the indentation in front of "ENDMSG" can be tabs only. If your lame-butt text editor sticks spaces in there, the shell script will get a syntax error. Here is the script:

     #!/bin/sh
     #
     # A shell script that can be used by the UPS power monitor to send messages
     # to root when power failures occur.
     #
     #
     # Source the UPS configuration.
     #
     if [ -f /etc/sysconfig/upsd ]; then
        . /etc/sysconfig/upsd
     fi
     #
     # Source the clustering configuration.
     #
     if [ -f /etc/sysconfig/clustering ] ; then
         . /etc/sysconfig/clustering
     else
         SERVERROLE=Standalone
     fi
     if [ x"$SERVERROLE" == x ]; then
         SERVERROLE=Standalone
     fi
     #
     # Determine which UPS boxes we are logging to.
     #
     if [ ${SERVERROLE} = "Primary" ] ; then
         UPS_BOXES=$UPS_BOXES_PRIMARY
     else
         if [ ${SERVERROLE} = "Secondary" ] ; then
             UPS_BOXES=$UPS_BOXES_SECONDARY
         fi
     fi
     #
     # Write the event to the log, if there is one.
     #
     if [ x"$LOG_PATH" != x ]; then
      timestamp=`date "+%Y/%m/%d %H:%M:%S"`
      for LogBox in $UPS_BOXES; do
          echo $UPSNAME | grep -q $LogBox
          matval=$?
          if [ $matval = 0 ] ; then
              echo $timestamp EVENT: $1 >> ${LOG_PATH}.$LogBox
          fi
      done

fi
#
# Some events we only log.
#
if ([ x"$NOTIFYTYPE" != xONBATT ]) && ([ x"$NOTIFYTYPE" != xONLINE ]) \

      && ([ x"$NOTIFYTYPE" != xREPLBATT ]) \
      && ([ x"$NOTIFYTYPE" != xSHUTDOWN ]) \
      && ([ x"$NOTIFYTYPE" != xOVERTEMP ]); then
      exit 0
     fi
     #
     # Email the message to root so that they can see everything that's going on.
     # After all, if you're omnipotent, you need to know everything.
     #
     HostName=`hostname`
     if [ x"$NOTIFYTYPE" != xSHUTDOWN ]; then
      /bin/mail -s "Message from the UPS" root <<-ENDMSG
          The power monitor on $HostName has generated the following message:
          $1
          ENDMSG
     else
      /bin/mail -s "Urgent message from the UPS" root <<-ENDMSG
          The power monitor on $HostName has generated the following message:
          $1
          ENDMSG
     fi

Note that, in the above script, the two sets of lines between "/bin/mail -s ... <<-ENDMSG" and up to and including the line with "ENDMSG" must either not be indented at all or only indented with actual tab characters (not blanks). If they are not, the script will fail.

Also, don't forget to add execute permissions to the script after you create it:

     su
     chmod ugo+x /etc/ups/notify

Then, it wouldn't hurt try it out after you've got it all set up. For example:

     UPSNAME=bevatron; export UPSNAME
     NOTIFYTYPE=ONBATT; export NOTIFYTYPE
     /etc/ups/notify "This is a test"

Check that root receives the message and that the message gets logged to bevatron's log file.

/etc/ups/hosts.conf:

Copy the file hosts.conf.sample. Add all of the machines that you want to be able to monitor from the Web. Also add the name of the logfile, if logged events will be displayed:

     MONITOR bevatron@localhost "jump-gate UPS"
     LOGFILE /var/log/upslog.bevatron

If you'll monitor the UPS via a Web server on another machine, add its information to the /etc/ups/hosts.conf file there, too.

/etc/ups/ftplogs:

If you'd like to build a consolidated graph of all your UPS activity and have a centralized server where logfiles can be copied for this purpose, you should create the file /etc/ups/ftplogs:

     #! /bin/sh
     #
     # ftplogs - Script to ftp the UPS logs to the primary server at regular
     #           intervals.
     #
     # This script is used both by cron, to send the current UPS logs to the
     # primary server, every 15 minutes, and by logrotate, to send the freshly
     # rotated UPS logs to the primary server whenever UPS logs are rotated.
     #
     #
     # Source the UPS configuration.
     #
     if [ -f /etc/sysconfig/upsd ]; then
        . /etc/sysconfig/upsd
     fi
     #
     # Source the clustering configuration.
     #
     if [ -f /etc/sysconfig/clustering ] ; then
         . /etc/sysconfig/clustering
     else
         SERVERROLE=Standalone
     fi
     if [ x"$SERVERROLE" == x ]; then
         SERVERROLE=Standalone
     fi
     #
     # Determine which UPS boxes we are logging to.  If we aren't the secondary
     # or a standalone system, there are no logfiles to FTP.
     #
     if [ x"$SERVERROLE" == xSecondary ]; then
         UPS_BOXES=$UPS_BOXES_SECONDARY
     else
         if [ x"$SERVERROLE" != xStandalone ]; then
             exit 0
         fi
     fi
     #
     # If there's no primary server defined, we're all done.
     #
     if [ x"$PRI_SERVER" == x ]; then
         exit 0
     fi
     #
     # If we were passed a logfile name, send it to the primary server directly.
     #
     if test x"$1" != x; then
         echo -e "user ups ItsASecret\\nbin\\nput ${LOG_PATH}.$1 \
             ${PRI_LOG_PATH}.$1" | ftp -n $PRI_SERVER
     #
     # For all of the UPS on this system, send the logs to the primary.
     #
     else
         for LogBox in $UPS_BOXES; do
             echo -e "user ups ItsASecret\\nbin\\nput ${LOG_PATH}.$LogBox \
                 ${PRI_LOG_PATH}.$LogBox" | ftp -n $PRI_SERVER
         done
     fi

In the FTP commands in the script, you should pick a user that is valid on the primary server and use the right password for that user. Once you've saved the script, don't forget to add execute permissions to it:

     su
     chmod ugo+x /etc/ups/ftplogs

Next, on the primary server, you should create a couple of empty log files with the correct permissions so that FTP can overwrite them without getting permission denied:

     su
     touch /var/log/upslog.bevatron /var/log/upslog.bevatron.1
     chown root:ups /var/log/upslog.bevatron
     chmod g+w /var/log/upslog.bevatron

Then, it wouldn't hurt try out the script, now that you've got it all set up. For example:

     /etc/ups/ftplogs

Check on the primary server that the log files get copied over.

If you want the UPS to be shown in the graph of UPS activity, add its name and full load power to /etc/ups/upsplot.pl:

     my @UPSNames = (                        # Names of UPS boxes                    
         "Bevatron",
              .
              .
              .
     my @UPSWatts = (                        # Full load wattages of UPS boxes       
         466,
              .
              .
              .

Now, you can add the script to the cron table on the secondary server so that it runs at regular intervals (e.g. every 15 minutes), as shown in the next section.

/etc/crontab:

To schedule all of the UPS-related activities, add the following to your crontab:

     # Push the UPS logs over to the primary server every 15 minutes.
     05,20,35,50 * * * * root /etc/ups/ftplogs
     # Twice a month, have the UPS check its battery.
     00 10 4,18 * * root /etc/ups/batterytest bevatron

Pick some suitable times that won't collide with other machines sending their UPS files to the central server (if you care). Also, if the receiving server is rotating the copied logs (this need not be the case, since the sending server is rotating its logs and the copied log always replaces the log on the receiving server, thereby ensuring that rotation on the sending server is sufficient to guarantee that log never grows too big), you should time the push to be a few minutes after the receiving server rotates its logs so that it can get a good, rotated copy of the last log before the new log is sent over top of it. Typically, logrotate runs out of /etc/cron.daily which is usually run at 04:02 each day. Consequently, the value of five minutes past the hour (chosen above) is a good choice.

Once again, if you care, schedule the times for the battery test on days when the other UPS are not also testing their batteries (you don't want all the machines down at once, do you).

Note that most UPS will usually come with automatic self-test turned on and set to every 14 days. This means that the UPS will run its battery test itself every 14 days, exactly 1209600 seconds after it is turned on. How convenient is that? If you'd rather the test was done when you decide, in your crontab, you should turn off this dubious feature like so:

     /usr/local/ups/bin/upsrw -s ups.test.interval=0 -u username -p password \
       upsname@localhost

/etc/logrotate.conf, /etc/logrotate.d/ups:

Add the new UPS' logfile to either the global logrotate config file (/etc/logrotate.conf) or the specific UPS config file (/etc/logrotate.d/ups):

     /var/log/upslog.bevatron {
         notifempty
         missingok
         create 0664 root ups
         copytruncate
         postrotate
             echo HEADER: Bevatron >/var/log/upslog.bevatron
             /etc/ups/ftplogs bevatron.1
         endscript
     }

/etc/rc.d/init.d/upsd:

Install the following script using "chkconfig --add upsd" and "chkconfig upsd on". Don't forget to set its permissions to "ugo+x":

     #! /bin/sh
     #
     # upsd - Script to start/stop the NUT UPS monitoring and power down daemons.
     #
     # chkconfig: 2345 19 81
     # description: Uninterruptable Power Supply monitoring and power down daemons
     #
     # pidfile: /var/lock/subsys/upsd
     # pidfile: /var/lock/subsys/upsmon
     # pidfile: /var/lock/subsys/upsdrivers.upsname
     # pidfile: /var/lock/subsys/upslog.upsname
     # config:  /etc/ups/*
     #
     #
     # Define the install path for the UPS binaries, etc.
     #
     INSTALL_PATH="/usr/local/ups"
     #
     # Load the RedHat functions.
     #
     if [ -f /etc/redhat-release ]; then
         . /etc/rc.d/init.d/functions
     fi
     #
     # Source the UPS configuration.
     #
     if [ -f /etc/sysconfig/upsd ]; then
        . /etc/sysconfig/upsd
     fi
     #
     # Source the clustering configuration.
     #
     if [ -f /etc/sysconfig/clustering ] ; then
         . /etc/sysconfig/clustering
     else
         SERVERROLE=Standalone
     fi
     if [ x"$SERVERROLE" == x ]; then
         SERVERROLE=Standalone
     fi
     #
     # Determine which UPS boxes we are starting up.
     #
     if [ ${SERVERROLE} = "Primary" ] ; then
         UPS_BOXES=$UPS_BOXES_PRIMARY
     else
         if [ ${SERVERROLE} = "Secondary" ] ; then
             UPS_BOXES=$UPS_BOXES_SECONDARY
         fi
     fi
     #
     # Upon startup, start all the UPS drivers that are configured in
     # /etc/ups/ups.conf (or wherever you put it).
     #
     # Next, start the UPS daemon to begin collecting information about all of
     # the connected UPS'.
     #
     # Then, start the power monitoring daemon to watch for low power conditions
     # and shut down the machine, if found.
     #
     start()
         {
         #
         # Start a driver for each of our UPS.
         #
         for UPSBox in $UPS_BOXES; do
          echo -n "NUT starting UPS driver for $UPSBox: "
          $INSTALL_PATH/bin/upsdrvctl start $UPSBox >/dev/null 2>&1
          startval=$?
          if [ $startval = 0 ] ; then
              touch /var/lock/subsys/upsdrivers.$UPSBox
              echo_success
          else
              echo_failure
          fi
          echo
      done
      #
      # Start the UPS daemon to process service requests.
      #
      echo -n "NUT starting UPS daemon: "
      $INSTALL_PATH/sbin/upsd >/dev/null 2>&1
      startval=$?
      if [ $startval = 0 ] ; then
          touch /var/lock/subsys/upsd
          echo_success
          echo
      else
          echo_failure
          echo
          return $startval
      fi
      #
      # Start power monitoring.
      #
      echo -n "NUT starting power monitor: "
      $INSTALL_PATH/sbin/upsmon >/dev/null 2>&1
      startval=$?
      if [ $startval = 0 ] ; then
          touch /var/lock/subsys/upsmon
          echo_success
          echo
      else
          echo_failure
          echo
          return $startval
      fi
      #
      # If the user has given us a logging directory, start up logging.
      #
      if [ x"$LOG_PATH" != x ]; then
          echo -n "NUT starting UPS log: "
          timestamp=`date "+%Y/%m/%d %H:%M:%S"`
          #
          # Start up logging for each UPS box.
          #
          # Note that, above, we could have failed to start one or more UPS
          # and ignored the failure.  Here, since it is the last step, we
          # abort upon the failure of any log.
          #
          if [ x"$LOG_INTERVAL" == x ]; then
              LOG_INTERVAL=30
          fi
          for UPSBox in $UPS_BOXES; do
              if [ ! -f ${LOG_PATH}.$UPSBox ]; then
                  echo HEADER: $UPSBox > ${LOG_PATH}.$UPSBox
              fi
              echo $timestamp EVENT: Starting UPS logging \
                  >> ${LOG_PATH}.$UPSBox
              if [ x"$UPS_GROUP" != x ]; then
                  chgrp $UPS_GROUP ${LOG_PATH}.$UPSBox
                  chmod g=rw ${LOG_PATH}.$UPSBox
              fi
              $INSTALL_PATH/bin/upslog ${UPSBox}@localhost \
                  ${LOG_PATH}.$UPSBox $LOG_INTERVAL \
                  "%TIME @Y/@m/@d @H:@M:@S% %VAR input.voltage% \
                      %VAR output.voltage% %VAR input.frequency% \
                      %VAR battery.charge% %VAR ups.load% [%VAR ups.status%] \
                      %VAR ups.temperature%" \
                  >/dev/null 2>&1
              startval=$?
              if [ $startval = 0 ] ; then
                  touch /var/lock/subsys/upslog.$UPSBox
              else
                  echo_failure
                  echo
                  return $startval
              fi
          done
          echo_success
          echo
      fi
      #
      # We're all done with startup.
      #
      return $startval
      }

#
# Upon shutdown, do all of the startups in reverse: logging; power monitor; # UPS daemon; UPS drivers.
#
stop()

      {
      #
      # Shutdown logging for any log that we started.
      #
      echo -n "NUT stoping UPS log: "
      timestamp=`date "+%Y/%m/%d %H:%M:%S"`
      for UPSBox in $UPS_BOXES; do
          if [ -f /var/lock/subsys/upslog.$UPSBox ]; then
              LogPID=`ps -eo pid,args | grep upslog | grep $UPSBox \
                  | sed -n 's/^ \([0-9]\).*/\1/p'`
              if [ x"$LogPID" != x ]; then
                  kill -9 $LogPID
                  stopval=$?
                  echo $timestamp EVENT: Stopping UPS logging \
                      >> ${LOG_PATH}.$UPSBox
                  [ $stopval = 0 ] && rm -f /var/lock/subsys/upslog.$UPSBox
              fi
          fi
      done
      echo_success
      echo
      #
      # Stop power monitoring.
      #
      if [ -f /var/lock/subsys/upsmon ]; then
          echo -n "NUT stoping power monitor: "
          $INSTALL_PATH/sbin/upsmon -c stop >/dev/null 2>&1
          stopval=$?
          if [ $stopval = 0 ] ; then
              rm -f /var/lock/subsys/upsmon
              echo_success
          else
              echo_failure
          fi
          echo
      fi
      #
      # Stop the UPS daemon.
      #
      if [ -f /var/lock/subsys/upsd ]; then
          echo -n "NUT stoping UPS daemon: "
          $INSTALL_PATH/sbin/upsd -c stop >/dev/null 2>&1
          stopval=$?
          if [ $stopval = 0 ] ; then
              rm -f /var/lock/subsys/upsd
              echo_success
          else
              echo_failure
          fi
          echo
      fi
      #
      # Stop all of our UPS drivers.
      #
      for UPSBox in $UPS_BOXES; do
          echo -n "NUT stoping UPS driver for $UPSBox: "
          $INSTALL_PATH/bin/upsdrvctl stop $UPSBox >/dev/null 2>&1
          stopval=$?
          if [ $stopval = 0 ] ; then
              rm -f /var/lock/subsys/upsdrivers.$UPSBox
              echo_success
          else
              echo_failure
          fi
          echo
      done
      return 0
      }

#
# See how we were called.
#
case "$1" in

      #
      # Start.
      #
      start)
          start
          RETVAL=$?
          ;;
      #
      # Stop.
      #
      stop)
          stop
          RETVAL=$?
          ;;
      #
      # Restart or reload (whatever).
      #
      restart|reload)
          stop
          start
          RETVAL=$?
          ;;
      #
      # Conditional restart.
      #
      condrestart)
          if [ -f /var/lock/subsys/upsdrivers ]; then
              stop
              start
              RETVAL=$?
          fi
          ;;
      #
      # Give the status of all of the NUT components that are running.
      #
      status)
          #
          # If none of the UPS are running, assume that NUT is down.
          #
          if [ ! -f /var/lock/subsys/upsdrivers ]; then
              echo NUT is down
              exit 1
          fi
          #
          # Let's check each UPS.
          #
          for UPSBox in $UPS_BOXES; do
              $INSTALL_PATH/bin/upsc $UPSBox output.voltage >/dev/null 2>&1
              RETVAL=$?
              if [ $RETVAL -eq 0 ]; then
                  echo UPS $UPSBox is functioning normally
              else
                  echo UPS $UPSBox is down
              fi
          done
          #
          # Check the UPS daemon.
          #
          status upsd
          #
          # Check the power monitor.
          #
          status upsmon
          #
          # If we're logging then let's see what we're logging.
          #
          if [ x"$LOG_PATH" != x ]; then
              status upslog
              RETVAL=$?
              if [ $RETVAL -eq 0 ]; then
                  for UPSBox in $UPS_BOXES; do
                      if [ -f /var/lock/subsys/upslog.$UPSBox ]; then
                          echo UPS $UPSBox is being logged to $LOG_PATH.$UPSBox
                      fi
                  done
              fi
          fi
          ;;
      #
      # Help text.
      #
      *)
          echo $"Usage: $0 {start|stop|restart|condrestart|status}"
          exit 1

esac

     exit $RETVAL

/etc/rc.d/init.d/upsdown:

To facillitate physical shutdown of the UPS power, when the system is shut down, install the following script using "chkconfig --add upsdown" and "chkconfig upsdown on". Don't forget to set its permissions to "ugo+x":

     #! /bin/sh
     #
     # upsd - Script to shut down the UPS upon system shutdown due to \
     #        power failure.
     #
     # Revision History:
     # ewilde      2003Apr06  Initial coding.
     #
     # chkconfig: 12345 01 99
     # description: Shut down Uninteruptable Power Supply on power fail shutdown
     #
     # This script runs on startup, right after new microcode has been installed
     # on the machine but before any file system activity.  It can sleep for a
     # while until the UPS batteries have a chance to recharge to a sufficient
     # level to ensure an orderly shutdown, should power fail again.  If you wish
     # to do this, set the START_SLEEP value to a valid "sleep(1)" value (e.g.
     # "5m") and make sure POWERDOWNFLAG points to the same file as found in the
     # upsmon.conf file.
     #
     # It also runs on shutdown, as the system cleans up after entering runlevel
     # 0 (shutdown) or 6 (reboot).  If the UPS POWERDOWNFLAG is set, it physically
     # powers off the UPS.  This should only happen in runlevel 0.
     # Define the install path for the UPS binaries, etc.
     INSTALL_PATH="/usr/local/ups"
     POWERDOWNFLAG="/etc/killpower"
     START_SLEEP=""
     if [ -f /etc/redhat-release ]; then
         . /etc/rc.d/init.d/functions
     fi
     # See how we were called.
     case "$1" in
      # Start.
      start)
          if [ -f $POWERDOWNFLAG ]; then
              echo -n "NUT waiting for UPS batteries to recharge: "
              if [ x"$START_SLEEP" != x ]; then
                sleep $START_SLEEP
              fi
              echo_success
              echo
          fi
          ;;
      # Stop.
      stop)
          if [ -f $POWERDOWNFLAG ]; then
              echo -n "NUT shutting down the UPS: "
              echo_success
              echo
              $INSTALL_PATH/bin/upsdrvctl shutdown
          fi
          ;;
      # Help text (pushing it, I know).
      *)
          echo $"Usage: $0 {start|stop}"
          exit 1

esac

     exit 0

Change the group ownership of the UPS port(s) to the ups user:

     chgrp ups /dev/ttyS2

If you have one of the later versions of Linux that use udev for dynamically creating the "/dev" device space, you will, as well, need to hack the udev rules for the tty device. These can be found in the /etc/udev/rules.d dirctory, typically in the file /etc/udev/rules.d/50-udev.rules. Add something to the effect of:

     # Special case for the UPS devices.
     KERNEL=="ttyS2",                NAME="%k", GROUP="ups", MODE="0660",
                                     OPTIONS="last_rule"

Add these lines before the general case rules for tty devices.

Alternately, later installs of NUT add a set of rules for the USB drivers in a file named 52_nut-usbups.rules. You could add the following to that file instead of hacking the existing 50-udev.rules:

     # Special case for the UPS devices
     KERNEL=="ttyS1", group="nut", MODE="0660"

Some serial ports will come up with the correct baud rate and interrupt address set automagically. After you've made the changes to the new serial port, as described above, to make it accessible to the UPS userid, you should check that the serial port is configured correctly (reboot the machine first, if you had to change the rules in /etc/udev). To do this use:

     su
     setserial /dev/ttySx

If the system figures things out and sets the serial ports correctly, all on its own, go with its settings because this will cause a lot less grief, in the long run. However, if the type of UART, port address and interrupt vector, along with the baud rate, aren't set correctly (usually looking at /dev/ttyS0 will give some clues), you should add some lines to /etc/rc.serial to set the serial port up at boot time. If it already exists, you can edit file but, if it doesn't already exist, you can just create it with your text editor.

To determine what interrupt numbers and port addresses to use, you should list the PCI devices like this:

     /sbin/lspci -v

For each serial port, figure out from the information given by lspci what values to use and then add something like this to /etc/rc.serial:

     setserial /dev/ttyS2 port 0xdf88 UART 16550A irq 225 Baud_base 115200

When you're done, the permissions on /etc/rc.serial should be:

     -rw-r--r--    1 root     root          138 Aug  6  2005 /etc/rc.serial

Finally, not all UPS come with their control parameters set correctly (especially if you'v bought a refurbished one) so you may want to check that they are what you expect them to be:

     /usr/local/ups/bin/upsc upsname@localhost

To find out which parameters you can set, run upsrw with no options:

     /usr/local/ups/bin/upsrw upsname@localhost

If any of the settable parameters are set to values that you don't like, you can change them with upsrw, like this:

     /usr/local/ups/bin/upsrw -s ups.test.interval=1209600 -u username \
       -p password upsname@localhost

For a typical APC SmartUPS, you may wish to set the following:

     battery.alarm.threshold     L
     battery.charge.restart 00
     battery.date                [batdate]
     battery.runtime.low 120
     input.sensitivity           H
     input.transfer.high 132
     input.transfer.low 103
     output.voltage.nominal 115       (only necessary on 240V units)
     ups.delay.shutdown 020
     ups.delay.start 000
     ups.id                      [upsname]
     ups.test.interval 1209600   (see notes on periodic test, above)