CS01-HS Posted August 9, 2020 Share Posted August 9, 2020 (edited) Purpose: Shut down MacOS gracefully prior to system shutdown to extend battery runtime Setup: Cyberpower UPS connected to a Rapsberry Pi running NUT in netserver mode (see TUTORIAL: Networked NUT for Cyberpower UPS) MacOS VM (Mojave) 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 August 9, 2020 by CS01-HS Quote Link to comment
Recommended Posts
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.