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.):

change to 

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@ 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 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 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 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

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 earlyshutdown 300
AT ONLINE * CANCEL-TIMER earlyshutdown
AT LOWBATT * START-TIMER shutdowncritical 30
AT ONLINE * CANCEL-TIMER shutdowncritical

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:

 case $1 in
          logger -t upssched-cmd "The UPS has been on battery for awhile
          logger -t upssched-cmd "UPS on battery too long, forced shutdown"
          /usr/sbin/upsmon -c fsd
          logger -t upssched-cmd "UPS on battery critical, forced shutdown"
          /usr/sbin/upsmon -c fsd
          logger -t upssched-cmd "The UPS has been gone for awhile"
          logger -t upssched-cmd "Unrecognized command: $1"

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@ 1 monuser secret slave
SHUTDOWNCMD "/usr/sbin/shutdown -h now"
NOTIFYCMD /usr/sbin/upssched
POWERDOWNFLAG /etc/killpower

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!

7 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?

  2. Great article once again. I am interested in possibly sending an sms text to my phone when any of my UPSs go on battery, and possibly when they return to line power. Just curious what your approach might be? I found some good ideas in this forum Q:

    Also, just an idea for you (would love your opinion). To separate some of the NUT log msgs out from syslog, I added the following script file to /etc/rsyslog.d/0-nut.conf… part of me wonders if this might be another way to filter for the powers alerts and send an SMS msg but, I think your NUT-specific approach documented here is ideal.

    # NUT logging
    # Include USB msgs since montoring UPS via only USB
    if $msg contains “USB” or $msg contains “nut-” or $msg contains “UPS” then {
    action(type=”omfile” file=”/var/log/nut.log”)
    } else {
    if $syslogtag contains “ups” or $syslogtag contains “nut” then
    action(type=”omfile” file=”/var/log/nut.log”)

    Thx again for the great article.

  3. Just curious… let’s say I’m in an area that suffers from short power interruptions here and there, and I just want to page myself immediately when the UPS goes on battery, and immediately when it goes back on line power. Would my /etc/nut/upssched.conf look something like… ?

    AT ONBATT * START-TIMER onbatterypower 0
    AT ONLINE * CANCEL-TIMER onlinepower

    …or would you use some different NUT commands?

  4. OK, I am a bit confused here. Sorry, I am a bit new to Linux.

    Does the upsmon -c fsd command shut down the UPS, or does it shutdown upsmon?

    When does the Shutdown command for the RPi get executed?

    My desire would be to send a shutdown command to the ups with a delay on it, then send a push shutdown message to hub controller, and then shut down the RPI before the UPS shuts down. It looks like your script in upssched shuts down the ups at 300 seconds. when does the RPi Shutdown? It has to happen befor the UPS shuts down.

    What am I missing here?

    1. upsmon -c FSD does a forced shutdown by calling the command specified by SHUTDOWNCMD. It also tells slave upsmon instances that the final shutdown is underway and they shutdown the systems that they are configured to control.

      1. Thanks for the reply. OK So I can forget about shutting down the UPS. But to send shutdown commands to other devices attached to the same UPS before shutting down the RPi I would have to write some sort of script or shell file to send the two or three different commands to the other home automation controllers, and then the shutdown to the RPi? Does SHUTDOWNCMD allow you to execute a script or .sh file?

Leave a Reply

Your email address will not be published.

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