A solution to an obscure Network UPS Tools problem

published Jul 07, 2006, last modified Jun 26, 2013

USB UPSes fail to stop after emergency low-battery shutdown? Here's the solution.

If you have an UPS that is plugged in via USB to your computer, you may be very aware that the Network UPS Tools suite can't command the UPS to shut the load down (at least on Fedora Core), because USB is disabled when the system reaches a stable state that's suitable to kill the load. Of course, this creates problems for servers that shouldn't stop.

Now, what do you do? The system won't shut down. It will just sit there consuming battery power, and eventually the UPS will kill the load because of battery drainage. And that is (in theory) OK, because when power comes back, the server will boot and start serving in a matter of a few minutes. You want this to happen, especially if you can't physically reach your server.

But what happens if the electricity comes back up while shutting down, or while the system is just sitting there idle in the "before UPS load kill state"?

Result: a power failure can make your server stop serving. And you can't reboot it remotely, since the server is, for all practical purposes, fully shut down (except for power).

To solve this issue, I created a script that will attempt to drain the UPS battery for a preset amount of time. If power comes back on during the battery drainage timeout, the server will reboot when the timeout is finished. Result? Your server won't be rendered mute by a power failure.

Place this script in your /sbin/halt.local file.

DRAINSECONDS=600

if [ -f /etc/killpower ] ; then

 echo "---------------------------------------------------------------"
 echo "Power failure shutdown mode"

 echo "Syncing disks..."
 /bin/sync

 echo "Flushing buffer caches..."
 for device in /dev/hd? ; do /sbin/hdparm -q -f $device ; done

 echo "Reading /bin/sleep, /sbin/reboot and dependencies ahead..."
 cat /etc/ld.so.cache /lib/libm.so.6 /lib/librt.so.1 /lib/libc.so.6 /lib/libpthread.so.0 /bin/sleep /sbin/reboot > /dev/null

 echo "Setting disks to standby..."
 for device in /dev/hd? ; do /sbin/hdparm -q -y $device ; done

 echo "---------------------------------------------------------------"
 echo "System will remain on for $DRAINSECONDS seconds and then reboot."
 echo "The UPS will restart the system when power is back."
 echo "---------------------------------------------------------------"
 /bin/sleep $DRAINSECONDS

 echo "Time is up.  Restarting system."
 /sbin/reboot -d

fi