[TUTORIAL] MacOS NUT install (Physical and Virtual)


Recommended Posts

Purpose: Shut down MacOS gracefully prior to system shutdown to extend battery runtime

 

Setup: 

 

Requirements:

  • Xcode
  • Xcode command line tools
  • Macports

 

 

1. Update macports

sudo port selfupdate
sudo port upgrade

 

2. Install NUT

sudo port install nut

 

3. Create graceful shutdown script

This will mimic Apple Menu -> Shutdown

The upside: A clean startup (i.e. running apps won't be reopened on startup)

The downside: User dialogs like save prompts will prevent shutdown

sudo emacs /opt/local/etc/shutdown.applescript

Paste:

#!/usr/bin/osascript
tell application "loginwindow" to «event aevtrsdn»

 

4. Configure NUT client

sudo cp /opt/local/etc/upsmon.conf.sample /opt/local/etc/upsmon.conf
sudo emacs /opt/local/etc/upsmon.conf

Change/add the following values, substituting mac-username, ups-name, nut-ip, remote-nutuser and remote-nutuser-password

# Increase slave shutdown wait period
HOSTSYNC 120

# Works with pollinterval setting to prevent disconnection
DEADTIME 25

# Alerting twice/day about a battery change is excessive, make it once
RBWARNTIME 86400

# Replace (graceful shutdown)
SHUTDOWNCMD "sudo -u mac-username osascript /opt/local/etc/shutdown.applescript"

# Add monitor
MONITOR ups-name@nut-ip 1 remote-nutuser remote-nutuser-password slave

 

5. LaunchDaemon to run NUT on startup

sudo emacs /Library/LaunchDaemons/org.networkupstools.upsmon.plist

Paste:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>EnvironmentVariables</key>
        <dict>
          <key>PATH</key>
          <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/local/sbin:</string>
        </dict>
        <key>Label</key>
        <string>org.networkupstools.upsmon</string>
        <key>UserName</key>
        <string>root</string>
        <key>GroupName</key>
        <string>wheel</string>
        <key>ProgramArguments</key>
        <array>
                <string>/opt/local/sbin/upsmon</string>
                <string>-D</string>
        </array>
        <key>KeepAlive</key>
        <false/>
        <key>RunAtLoad</key>
        <true/>
</dict>
</plist>

Enable:

sudo launchctl load -w /Library/LaunchDaemons/org.networkupstools.upsmon.plist

 

6. Configure upssched to trigger shutdown 5 minutes (300 seconds) after power loss

sudo emacs /opt/local/etc/upsmon.conf

Update/add the following:

NOTIFYCMD "/opt/local/sbin/upssched"

NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC

Create the schedule config

sudo cp /opt/local/etc/upssched.conf.sample /opt/local/etc/upssched.conf
sudo emacs /opt/local/etc/upssched.conf

Update/add the following:

PIPEFN /opt/local/var/db/ups/upssched/upssched.pipe
LOCKFN /opt/local/var/db/ups/upssched/upssched.lock

# Start 5 minute shutdown timer when power's lost
AT ONBATT * START-TIMER onbattwarn 300

# Cancel timer if power comes back
AT ONLINE * CANCEL-TIMER onbattwarn

Create the pipe/lock directory

sudo mkdir /opt/local/var/db/ups/upssched
sudo chown _nut:_nut /opt/local/var/db/ups/upssched

Create the command file

sudo cp /opt/local/bin/upssched-cmd /opt/local/bin/upssched-cmd.orig
sudo emacs  /opt/local/bin/upssched-cmd

Paste:

#! /bin/sh
#
# This script should be called by upssched via the CMDSCRIPT directive.
#
# Here is a quick example to show how to handle a bunch of possible
# timer names with the help of the case structure.
#
# This script may be replaced with another program without harm.
#
# The first argument passed to your CMDSCRIPT is the name of the timer
# from your AT lines.

case $1 in
        onbattwarn)
                logger -t upssched-cmd "Received signal: $1 ; Executing shutdown"
                /opt/local/sbin/upsmon -c fsd
                ;;
        *)
                logger -t upssched-cmd "Unrecognized command: $1"
                ;;
esac

 

7. (OPTIONAL) Prevent apps from re-opening after dirty shutdown

If you have your iTunes or iPhoto libraries on networked drives and they open before the drive is mounted it will cause problems, so let's prevent that permanently by blanking the "open apps" files then making them un-writable

sudo echo > ~/Library/Preferences/ByHost/com.apple.loginwindow*
sudo chown root ~/Library/Preferences/ByHost/com.apple.loginwindow*
sudo chmod 000 ~/Library/Preferences/ByHost/com.apple.loginwindow*

 

8. Restart and confirm NUT client (upsmon) is running

Apple Menu -> Restart

ps -ef | grep upsmon

All done!

 

 

References:

https://gist.github.com/hdml/fcad80f6d483709f5e51133669e8b7ca

https://apple.stackexchange.com/questions/129327/avoiding-all-apps-reopening-when-os-x-crashes

https://alvinalexander.com/mac-os-x/launchd-examples-launchd-plist-file-examples-mac/

https://networkupstools.org/docs/user-manual.chunked/ar01s07.html

Edited by CS01-HS
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.