How to Configure an Orderly Shutdown on a Raspberry Pi

Once you have NUT-tools configured on your Raspberry to monitor your UPS, the next step is configuring the slaves. The slaves are your servers and other computers that are plugged into the UPS. Looking at my UPS stats on the NUT web server pages, it looks like I’ve got about 16 minutes of runtime under the current load. This post will lead you through configuring your server to shutdown after 10 minutes. Honestly, this whole place is on standby generator power, so the lights might go out for 15-20 seconds during the switchover. The UPS will handle that, easy! But if the generator fails, I’ve got to make sure that someone does a “shutdown -h now” on my LINUX servers. And that someone? NUT!

The Story So Far…

So far, we’ve got nut-tools running on a Raspberry Pi 3. It’s got a USB connection to the UPS and my webserver is plugged in to that UPS. IF the power is out for 10 minutes or more, it’s not coming back on anytime soon, so I need NUT to send a command to shutdown the server.

The last Raspberry we configured was the “master”. It’s got a USB connection to the UPS and watches for the UPS switching between mains and battery power. Now, it’s time to configure the “slaves” or the computers that hear that Raspberry screaming that the lights are out!

How to Install a NUT client

First, install the nut client:

sudo apt install nut-client

To get the slave talking to the master, you’ll have to edit two files: nut.conf and upsmon.conf. The nut.conf file is used to put the software into slave mode. Edit / add the following line to nut.conf. (I just put it right at the end so it’s easy to find.):

MODE=none
change to 
MODE=netclient

Next, we’re going to add a line to upsmon.conf. You’ll need the name of the UPS, the username, and the password that we configured on the master.

MONITOR <system> <powervalue> <username> <password>  ("master"|"slave")
change to 
MONITOR servers@192.168.1.193 1 monuser secret slave

This time the MONITOR is a little different. It’s watching the Raspberry that’s running NUT, not the UPS directly. ups is the name of the UPS that my servers are plugged into. The IP address is that of the Raspberry. 1 is the powermode. Just leave this at 1. monuser is the user that I configured. secret is the password. slave is the mode. Restart:

systemctl restart nut-monitor.service

Now, check your connection to the master. If you’re copying my config, the test looks like this. upsc is the command. “servers” is the name of the UPS. “ups” is the name of the raspberry that has the USB connection to the actual UPS:

root@server1:~# upsc servers@ups
 Init SSL without certificate database
 battery.charge: 100
 battery.charge.low: 10
 battery.charge.warning: 20
 battery.mfr.date: CPS
 battery.runtime: 1008
 battery.runtime.low: 300
 battery.type: PbAcid
 battery.voltage: 27.2
 battery.voltage.nominal: 24
 device.mfr: CPS
 device.model: CP1350AVRLCDa
 device.serial: CTJJY2003442
 device.type: ups
 driver.name: usbhid-ups
 driver.parameter.pollfreq: 30
 driver.parameter.pollinterval: 15
 driver.parameter.port: auto
 driver.parameter.product: .50A.
 driver.parameter.synchronous: no
 driver.version: 2.7.4
 driver.version.data: CyberPower HID 0.4
 driver.version.internal: 0.41
 input.voltage: 124.0
 input.voltage.nominal: 120
 output.voltage: 140.0
 ups.beeper.status: enabled
 ups.delay.shutdown: 20
 ups.delay.start: 30
 ups.load: 35
 ups.mfr: CPS
 ups.model: CP1350AVRLCDa
 ups.productid: 0501
 ups.realpower.nominal: 815
 ups.serial: CTJJY2003442
 ups.status: OL
 ups.test.result: No test initiated
 ups.timer.shutdown: -60
 ups.timer.start: -60
 ups.vendorid: 0764
 root@server1:~#

What to Do When the Lights Go Out

Now, we need to instruct nut what to do when it hears from the master that the UPS battery is draining! Edit upsmon.conf and search for SHUTDOWNCMD. That should lead you to the definition of how to run the shutdown command. Run “which shutdown” on your server to see where the command is. On my system it’s in: /usr/sbin/shutdown so I need to edit the line in upsmon.conf to look like this:

SHUTDOWNCMD "/usr/sbin/shutdown -h now"

Next, we’ll edit upssched.conf. This is where you can configure the UPS statuses and what nut should do about them. The format for each line is: AT notifytype upsname command The commands themselves are configured in /usr/bin/upssched-cmd The timers take an argument that is the number of seconds. After that number of seconds, the command is sent to upssched-cmd for immediate execution. The CMDSCRIPT line must be first! PIPEFN and LOCKFN are files that get created by the system. You just have to specify their names and locations. PIPEFN is the pipe facility that allows upssched to talk to the script. Next, you have all of your messages coming from the monitor (named “*”) and what to do about them. The lower case word is the argument that gets sent to the command processor, upssched-cmd.

CMDSCRIPT /usr/bin/upssched-cmd

PIPEFN /etc/nut/upssched/nut.pipe
LOCKFN /etc/nut/upssched/nut.lock

AT ONBATT * START-TIMER onbatt 20
AT ONLINE * CANCEL-TIMER onbatt
AT ONBATT * START-TIMER earlyshutdown 300
AT ONLINE * CANCEL-TIMER earlyshutdown
AT LOWBATT * START-TIMER shutdowncritical 30
AT ONLINE * CANCEL-TIMER shutdowncritical
AT COMMBAD * START-TIMER upsgone 30
AT COMMOK * CANCEL-TIMER upsgone

Note the change to the path for upssched-cmd. Don’t get tripped up by the similarity of the names /usr/bin/upssched-cmd and /etc/nut/upssched.conf!

Here’s my /usr/bin/upssched-cmd:

#!/bin/sh
 case $1 in
       onbatt)
          logger -t upssched-cmd "The UPS has been on battery for awhile
          ;;
       earlyshutdown)
          logger -t upssched-cmd "UPS on battery too long, forced shutdown"
          /usr/sbin/upsmon -c fsd
          ;;
       shutdowncritical)
          logger -t upssched-cmd "UPS on battery critical, forced shutdown"
          /usr/sbin/upsmon -c fsd
          ;;
       upsgone)
          logger -t upssched-cmd "The UPS has been gone for awhile"
          ;;
       *)
          logger -t upssched-cmd "Unrecognized command: $1"
          ;;
 esac

Check what’s happening here. Most of these commands call upsmon. upsmon is the client process that is responsible for the most important part of UPS monitoring—shutting down the system when the power goes out. Once again, you’ll want to check the path (with “which”) of the location of this all too important player. Otherwise you can put whatever you like in here: commands to email you, run other processes, or whatever you need.

upsmon.conf is extensively documented within. You can read what needs to be configured. Here’s what I ended up using after tinkering with it for a couple of hours…

MONITOR printer@192.168.1.193 1 monuser secret slave
MINSUPPLIES 1
SHUTDOWNCMD "/usr/sbin/shutdown -h now"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE       SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT       SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT      SYSLOG+WALL+EXEC
NOTIFYFLAG FSD          SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK       SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD      SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN     SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT     SYSLOG+WALL+EXEC
NOTIFYFLAG NOCOMM       SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT     SYSLOG+WALL+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5

Feeling Brave?

OK. Time for the big test. Restart upsmon and pull the plug on the UPS! You should see a couple of wall messages. The UPS should be beeping. Depending on how you sent the timers in upsmon, your server should shut down any minute now!

Author: John

2 thoughts on “How to Configure an Orderly Shutdown on a Raspberry Pi

  1. Hi, can I install both the master and the slave instance on the rpi if the rpi is the server i’d like to be shut down in a properly manner?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.