Economy of Effort: Delayed System Shutdown

by Jason Deraleau

It's Friday. It's the end of the business week and no one wants to work any harder than he or she has to. Some might call that laziness, but it's really about having an economy of effort. Just enough to keep the system moving AND to keep your own sanity.


As tribute to you, the hardworking Mac users of the world, I'm going to do my part to help you finish up the work week. Each Friday, I'll share a script, workflow, widget, or other utility that somehow helps make my work faster or my life easier. These might not be tools that are perfect for every person, but they will certainly help some of you. And if you have something you'd like to share, please feel free to forward it along. I always appreciate a new way to save some time.


The Problem


Since the later years of the classic Mac OS, it's been possible to schedule the startup and shutdown times of Apple computers using the Energy preferences. While a couple of early Mac OS X releases lacked this convenience, it has since been re-added to the OS. In Tiger, you can find these settings in the Energy Saver preferences pane ( Apple menu -> System Preferences -> Energy Saver). In the lower right-hand corner of the pane is a button labeled Schedule. Click it and you'll see something like this:



Using these options, it is possible to schedule your Mac to start up at a given hour, as well as shut down (or sleep!) at your desired time. While this is certainly convenient if you want your machine up and running when you yourself get up and running in the morning, it doesn't feel quite complete in the shut down department. Sometimes, you don't want your machine to shut down at a specific time so much as after a certain amount of time has passed. For example, you're up late, uploading that new web template to your homepage and you don't want to wait for it to complete before you hit the sack.


In these situations, the Energy Saver preferences leave a lot to be desired. Sure, you could always set the shut down time by simply adding the necessary minutes to what your Mac's clock is showing you, but that is hardly a convenient solution. You could accomplish this in the Terminal by using the shutdown command, but that isn't exactly an elegant solution. Faced with this problem recently, I employed AppleScript to create a delayed shut down.


The Solution


My plan for the script was simple. First, pop open a dialog box to ask the user for the number of minutes that should pass before the shut down occurs. Then, wait for that time to pass before shutting down the system. So, my initial script looked something like this:

Note: Many of these lines of code are too long to fit in the width of this page. Where necessary, white space has been inserted to fit the site template. Long lines have been broken up into multiple lines, with each segment indented by a single space.



display dialog "Please enter the time to wait in minutes:" default answer "5"
 buttons {"Cancel", "Shut Down"} default button "Cancel"

set myResult to the result
set delayTime to ((the text returned of the myResult) as number)

delay (delayTime * 60) -- Multiply minutes by 60 for seconds
tell application "System Events"
    shut down
end tell


While totally functional, the script doesn't offer much functionality. Perhaps I'm a MacBook user and I'd rather put my machine to sleep than have it shut down completely. So, I added a bit more code to give the user a choice:


display dialog "Please enter the time to wait in minutes and click the desired action:"
 default answer "5" buttons {"Cancel", "Sleep", "Shut Down"} default button "Cancel"

set myResult to the result
set delayTime to ((the text returned of the myResult) as number)
set desiredAction to the button returned of the myResult

delay (delayTime * 60) -- Multiply minutes by 60 for seconds
if desiredAction is "Sleep" then
    tell application "System Events"
        sleep
    end tell
else if desiredAction is "Shut Down" then
    tell application "System Events"
        shut down
    end tell
end if


Now the script is a little more versatile. It asks the user how many minutes it should wait and allows the user to specify which action should then be performed. My only concern at this point was that there isn't really any user notification involved in the process. While I could have used more dialog boxes to give feedback, I instead turned to Growl for my notification needs. Here then is the final script, including Growl calls for when the shut down is scheduled, as well as periodic Growl notifications as the shut down becomes imminent:


(**************************************************
Name: Delayed Shutdown.scpt
Purpose: Sleep or shut down the system after a given
 number of minutes have passed.
Version: 2006032701
Author: Jason Deraleau <jldera at mac dot com>
License: Attribution-ShareAlike Creative Commons License
**************************************************)


-- Pop a dialog and get the action/time from user.
display dialog "Please enter the time to wait in minutes and click the desired action:"
 default answer "5" buttons {"Cancel", "Sleep", "Shut Down"} default button "Cancel"


-- Populate variables
set myResult to the result
set delayTime to ((the text returned of the myResult) as number)
set desiredAction to the button returned of the myResult


-- Pop a Growl notification
set theDescription to "The system is scheduled to " & desiredAction & " in "
 & delayTime & " minute(s)."
tell application "GrowlHelperApp"
    notify with name "System Alert" title "Delayed Shutdown" description
     theDescription application name "jd System Scripts"
     icon of application "Dashboard.app"
end tell


-- Delay for (time minus 30 seconds) and pop another Growl notification
set delayTime to ((delayTime * 60) - 30)
delay delayTime
set theDescription to "The system is scheduled to " & desiredAction & " in 30 seconds."
tell application "GrowlHelperApp"
    notify with name "System Alert" title "Delayed Shutdown"
     description theDescription application name "jd System Scripts"
     icon of application "Dashboard.app"
end tell


-- Delay for 20 seconds and pop final Growl notification
delay 20
set theDescription to "The system is scheduled to " & desiredAction & " in 10 seconds."
tell application "GrowlHelperApp"
    notify with name "System Alert" title "Delayed Shutdown"
     description theDescription application name "jd System Scripts"
     icon of application "Dashboard.app"
end tell


-- Delay last 10 seconds and perform the desired action
delay 10
if desiredAction is "Sleep" then
    tell application "System Events"
        sleep
    end tell
else if desiredAction is "Shut Down" then
    tell application "System Events"
        shut down
    end tell
end if


Enjoy this script. I'll be back with another treat next Friday.


4 Comments

Mike A
2006-04-07 12:04:44
Shameless self-promotion I know, but my app "Pause" will do a delayed shutdown for you a heck of a lot easier!
lieb
2006-04-07 15:36:46
Seems like a lot of work to duplicate the built in shutdown command. /sbin/shutdown -h 17:00 "System going down at 5 PM" is an old unix command that lives on in OS X. Of course it can't growl.
Andy S
2006-04-09 16:42:12
Of course, what I really want is a "Perform my list of tasks, then shutdown" command. That list might include making sure my iDisk is synched, making sure my calendars/contacts are synched, uploading stickybrain file to .mac, sending any delayed email messages, perhaps even a backup or check permissions...
lliot Marshall
2008-07-27 00:44:25
this is really cool and i've been wanting to do this. how do i use this script to make it work?