Last updated 2016/03/22
Return to the Suffield Academy Network Documentation Homepage
A printable version of this document is also available.
We use NUT to manage our UPSes and automated shutdown of servers (see our NUT documentation for more information). However, NUT has not been ported to run on Mac OS 9, so our older servers would not automatically shut down when a power failure took place.
To work around this issue, we built a small set of scripts that send remote AppleScript events to a Mac running OS 9. While basic, these commands provide enough functionality to shut a machine down remotely.
While these scripts focus on power failure shutdowns, they are very basic and easily adapted to other uses. See the code in the following sections for more information.
The full shutdown package relies on three main components:
To configure the target, we must install a few scripts on the system volume of the machine. We must also configure the system to receive and process remote AppleEvents.
In the
scripts/target
directory of the project, you will find two scripts:
Copy these scripts onto the target machine (the one running Mac OS 9).
On the target machine:
RemoteShutdown
.
Script Editor
application that
comes with OS 9. You may need to open the scripts from within the
application, or by dragging the scripts onto the application's icon.
.txt
extension (e.g., CommTest
and ForcedShutDown
).
RemoteShutdown
folder you
created at the root level of the hard drive.
You have now compiled the scripts correctly. Quit Script Editor
.
If you wish, you may delete the original script files (only the
compiled versions are needed for regular operation).
The target machine must be configured to receive remote events from other computers:
File Sharing
control panel on the target.
Make note of the IP address (or DNS name) of this machine, the username you created, and the associated password. You'll need these items later to connect to the machine and execute the shutdown scripts.
Note: if you will use a single source to shut down multiple targets, you may wish to use the same username and password for each target. There are security implications to having the same username and password for each machine, but it also makes sending commands to a large group of machines much easier.
The source machine (running Mac OS X) requires no system configuration to work with the targets. The source simply needs to fire the remote AppleEvent and send it to the target machine over the network.
The simplest way to fire the event is by using a command-line AppleScript. Open a terminal on the source machine and execute the following (the command should be input as a single line):
osascript -l AppleScript -e "tell Application \"Finder\" of
machine \"eppc://
username:
password@
hostname\"
to open file \"CommTest\" of folder \"RemoteShutdown\" of startup disk"
(A copy of this command lives in the
scripts/source
directory for this project.)
You must replace username, password, and hostname with the specific values for your target machine. The username and password are set in the File Sharing control panel on the target, and the IP address is set in the TCP/IP control panel.
Upon running the command, the target machine should launch the CommTest script and preset a dialog box. If it doesn't, the source machine should return an error message to help diagnose the problem.
Once you have the sample script working, you may try the ForcedShutDown script. If you are installing on a production machine, be careful not to shut it down accidentally!
We designed the remote shutdown script as part of our automated shutdown process during a power failure. This section describes how to integrate the scripts with NUT, our UPS management software. Note that the principles discussed here can be adapted to other uses with minimal effort.
To use NUT as a trigger, NUT must be configured to trigger an
upssched
script when power-related events occur.
Configuring NUT is beyond the scope of this document; please refer to our documentation for setting up NUT for more information.
Before proceeding, you should have NUT configured to call upssched
for ONBATT
, ONLINE
, and FSD
events. In turn, upssched
should invoke a script on the system that correctly parses these
events. We'll be modifying this script to add support for calling the
remote shutdown scripts.
As an example, the config files from our stock NUT config are shown below. We'll be working from these configurations in the sections below:
The upsmon.conf
file must include support for calling upssched
when power events occur. This means including the following lines:
NOTIFYCMD /usr/local/nut_upsmon/sbin/upssched NOTIFYFLAG ONBATT WALL+SYSLOG+EXEC NOTIFYFLAG ONLINE WALL+SYSLOG+EXEC NOTIFYFLAG FSD WALL+SYSLOG+EXEC
You may need to modify paths or modify lines to your liking. The lines above are an example of the minimum required configuration.
The upssched.conf
file tells NUT what script to call during
power-related events, and which events to listen for. You can
configure an event to trigger immediately (EXECUTE
), or to wait a
certain amount of time (START-TIMER
).
In the sample below, we start a timer during on-battery events, but execute immediately when we receive a forced shutdown request (e.g., when the battery is almost exhausted).
CMDSCRIPT /usr/local/nut_upsmon/bin/early-shutdown AT ONBATT * START-TIMER early-shutdown 120 AT ONLINE * CANCEL-TIMER early-shutdown AT FSD * EXECUTE forced-shutdown
The script early-shutdown
must handles the commands from
upssched
(e.g., early-shutdown
and forced-shutdown
)
and makes the calls to any additional scripts. This is where we add
our AppleScript code to shut down other machines.
Below is the stock early-shutdown
script from our NUT package. At
the moment, it simply shuts down the local machine. We'll be building
on this script to add the code to shut down other machines.
case "${1}" in early-shutdown) logger -t early-shutdown "Early Shutdown time has arrived!" /usr/local/nut_upsmon/sbin/upsmon -c fsd ;; forced-shutdown) logger -t early-shutdown "UPS Master sent Forced Shutdown Request" /usr/local/nut_upsmon/sbin/upsmon -c fsd ;; *) logger -t early-shutdown "Unknown command: ${1}" ;; esac
We'll assume that we need to shut down multiple target machines from a single source. To do so, we'll write a script that keeps a list of machines that must be shut down, and then sends each machine the proper commands.
We have a sample script, called
shutdown_os9
,
which is included in the
scripts/source
directory of this project. You should customize it
for your needs.
Because this script contains usernames and passwords, its permissions
should be set to only allow access to the NUT user (ups_mon
, in
this case):
chown nut_upsmon shutdown_os9 chmod 700 shutdown_os9
To actually invoke the shutdown script, we must add it to the script
that upssched
calls. In our NUT package, that script is called
early-shutdown
. We simply add the call to the script in the right
places, as shown below. We have a sample script, called
early-shutdown-with-remote
,
which is included in the
scripts/nut
directory of this project.
Note that NUT must be correctly configured to call this script via
upssched
. See our NUT documentation for more
information on configuring NUT.