Skip to content

Instantly share code, notes, and snippets.

@MitsuhaMiyamizu
Forked from hdml/nut_osx.txt
Created March 4, 2024 14:31
Show Gist options
  • Save MitsuhaMiyamizu/b68a84bec4ab26ed8d0c0dbd90c33286 to your computer and use it in GitHub Desktop.
Save MitsuhaMiyamizu/b68a84bec4ab26ed8d0c0dbd90c33286 to your computer and use it in GitHub Desktop.
Network UPS Tools on macOS High Sierra (netclient)
#install homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
#install network ups tools
brew update
brew install nut
#create directories and change permissions
sudo mkdir -p /var/state/ups/upssched/
sudo chown -R `whoami`:nobody /var/state/ups
sudo chmod 775 /var/state/ups/
sudo chmod 664 /var/state/ups/*
sudo chmod 775 /var/state/ups/upssched/
sudo chmod 640 /usr/local/Cellar/nut/2.7.4/etc/*
sudo chmod o+r /usr/local/Cellar/nut/2.7.4/etc/upssched.conf
cd /usr/local/Cellar/nut/2.7.4/etc/
mv nut.conf.sample nut.conf
vi nut.conf
MODE=netclient
:wq
mv upsmon.conf.sample upsmon.conf
vi uspmon.conf
# Set your remote server host and password
MONITOR ups@remotehost:3493 1 upsmon remotepassword slave
# Set your admin user that will execute the shutdown script
SHUTDOWNCMD "sudo -u localuser osascript /usr/local/Cellar/nut/2.7.4/bin/shutdown.applescript"
NOTIFYCMD "/usr/local/sbin/upssched"
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
:wq
#create LaunchDaemon that will fire up upsmon
sudo vi /Library/LaunchDaemons/org.networkupstools.upsmon.plist
<?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>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.networkupstools.upsmon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/sbin/upsmon</string>
<string>-D</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Library/Logs/upsmon.log</string>
<key>StandardErrorPath</key>
<string>/Library/Logs/upsmon.log</string>
</dict>
</plist>
:wq
mv upssched.conf.sample upssched.conf
#configuring for shutdown after 2min
vi upssched.conf
CMDSCRIPT /usr/local/Cellar/nut/2.7.4/bin/upssched-cmd
PIPEFN /var/state/ups/upssched/upssched.pipe
LOCKFN /var/state/ups/upssched/upssched.lock
AT NOCOMM * EXECUTE NOCOMM
AT COMMBAD * START-TIMER COMMBAD 10
AT COMMOK * CANCEL-TIMER COMMBAD COMMOK
AT FSD * EXECUTE FSD
AT LOWBATT * EXECUTE LOWBATT
AT LOWBATT * START-TIMER FSD 5
AT ONBATT * EXECUTE ONBATT
AT ONBATT * START-TIMER SHUTDOWN 60
AT ONLINE * EXECUTE ONLINE
AT ONLINE * CANCEL-TIMER SHUTDOWN
AT REPLBATT * EXECUTE REPLBATT
AT SHUTDOWN * EXECUTE SHUTDOWN
AT NOPARENT * EXECUTE NOPARENT
:wq
vi uspmon.conf
#unfortunately, we can't use SHUTDOWNCMD "/usr/bin/osascript -e 'tell app \"loginwindow\" to «event aevtrsdn»'"
#because of angle brakets (upsmon filtering them), so we'll create shutdown.applescript
#but if you don't need additional time for cancel shutdown - use second SHUTDOWNCMD
SHUTDOWNCMD "sudo -u Username /usr/local/Cellar/nut/2.7.3/bin/shutdown.applescript"
#SHUTDOWNCMD "/usr/bin/osascript -e 'tell app \"System Events\" to shut down'"
NOTIFYCMD "/usr/local/sbin/upssched"
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOCOMM SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
:wq
vi /usr/local/Cellar/nut/2.7.3/bin/shutdown.applescript
#!/usr/bin/osascript
tell application "loginwindow" to «event aevtrsdn»
:wq
vi /usr/local/Cellar/nut/2.7.3/bin/upssched-cmd
#! /bin/sh
case $1 in
ONLINE)
logger -t upssched-cmd "UPS on line power"
;;
ONBATT)
logger -t upssched-cmd "UPS on battery"
;;
LOWBATT)
logger -t upssched-cmd "UPS battery is low"
;;
FSD)
logger -t upssched-cmd "UPS forced shutdown in progress. System is going down!"
/usr/bin/osascript -e 'tell app \"System Events\" to shut down'
;;
COMMOK)
logger -t upssched-cmd "Communications with UPS established"
;;
COMMBAD)
logger -t upssched-cmd "Communications with UPS lost"
;;
SHUTDOWN)
logger -t upssched-cmd "Auto logout and shutdown proceeding. Executing graceful shutdown."
/usr/local/sbin/upsmon -c fsd
;;
REPLBATT)
logger -t upssched-cmd "UPS battery needs to be replaced"
;;
NOCOMM)
logger -t upssched-cmd "UPS is unavailable"
;;
NOPARENT)
logger -t upssched-cmd "upsmon parent process died - shutdown impossible"
;;
*)
logger -t upssched-cmd "Unrecognized UPS command: $1"
;;
esac
:wq
#launch daemon
sudo launchctl load /Library/LaunchDaemons/org.networkupstools.upsmon.plist
#it's done
#check status in Console.app, under /Library/Logs
#to debug
#change debug level from -D to -DDD at least - <string>-DDD</string>
#if you want to log your UPS voltages, create the org.networkupstools.upslog.plist LaunchAgent in this gist.
#replace your remote UPS host and user path in the output log "/Users/youruser"
#and 300 for the interval in seconds of the logging frequency (default 300 seconds = 5 mins)
<?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:/usr/local/sbin</string>
</dict>
<key>Label</key>
<string>org.networkupstools.upsmon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/upslog</string>
<string>-s</string>
<string>ups@remote-ups-host:3493</string>
<string>-l</string>
<string>/Users/youruser/Library/Logs/upslog.log</string>
<string>-i</string>
<string>300</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
<?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>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.networkupstools.upsmon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/sbin/upsmon</string>
<string>-D</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Library/Logs/upsmon.log</string>
<key>StandardErrorPath</key>
<string>/Library/Logs/upsmon.log</string>
</dict>
</plist>
#!/usr/bin/osascript
tell application "loginwindow" to «event aevtrsdn»
#! /bin/sh
case $1 in
ONLINE)
logger -t upssched-cmd "UPS on line power"
;;
ONBATT)
logger -t upssched-cmd "UPS on battery"
;;
LOWBATT)
logger -t upssched-cmd "UPS battery is low"
;;
FSD)
logger -t upssched-cmd "UPS forced shutdown in progress. System is going down!"
/usr/bin/osascript -e 'tell app \"System Events\" to shut down'
;;
COMMOK)
logger -t upssched-cmd "Communications with UPS established"
;;
COMMBAD)
logger -t upssched-cmd "Communications with UPS lost"
;;
SHUTDOWN)
logger -t upssched-cmd "Auto logout and shutdown proceeding. Executing graceful shutdown."
/usr/local/sbin/upsmon -c fsd
;;
REPLBATT)
logger -t upssched-cmd "UPS battery needs to be replaced"
;;
NOCOMM)
logger -t upssched-cmd "UPS is unavailable"
;;
NOPARENT)
logger -t upssched-cmd "upsmon parent process died - shutdown impossible"
;;
*)
logger -t upssched-cmd "Unrecognized UPS command: $1"
;;
esac
CMDSCRIPT /usr/local/Cellar/nut/2.7.4/bin/upssched-cmd
PIPEFN /var/state/ups/upssched/upssched.pipe
LOCKFN /var/state/ups/upssched/upssched.lock
AT NOCOMM * EXECUTE NOCOMM
AT COMMBAD * START-TIMER COMMBAD 10
AT COMMOK * CANCEL-TIMER COMMBAD COMMOK
AT FSD * EXECUTE FSD
AT LOWBATT * EXECUTE LOWBATT
AT LOWBATT * START-TIMER FSD 5
AT ONBATT * EXECUTE ONBATT
AT ONBATT * START-TIMER SHUTDOWN 60
AT ONLINE * EXECUTE ONLINE
AT ONLINE * CANCEL-TIMER SHUTDOWN
AT REPLBATT * EXECUTE REPLBATT
AT SHUTDOWN * EXECUTE SHUTDOWN
AT NOPARENT * EXECUTE NOPARENT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment