|< Day Day Up >|
Setting Up Automatic Script Execution
After you've mastered the skill of building useful automated process into scripts, you'll start wanting to set things up so that they run themselves automatically as well, instead of requiring you to start them manually. Not surprisingly, the Unix side of Mac OS X provides several flexible ways for you to set up the automation you need.
Making Shell Scripts Start at Login or at System Startup
Now that you know how to write shell scripts and run them as commands, making them start when you log in to your account, or making them start when the system starts, is straightforward.
You're already familiar with the login preferences settings and your ability to customize what programs start when you log in from it. An executable shell script is just another program as far as Unix is concerned, so you can configure scripts to start on login from there. If you're going to be working from the command line with any frequency, you might want to consider adding a single shell script to your login preferences and using that script to execute other scripts as necessary.
To add a shell script as an item that starts at system startup is also quite simple. Create a subdirectory for the script you want to run in the /Library/StartupItems/ folder and place the script or a link to the script in the directory, giving it the same name as the directory. When the system starts, the script will execute. Remember that it's not going to have a terminal attached, so if it does things such as echo data, the data will have nowhere to appear. In the next chapter, we'll cover the contents of the plist (properties list) file that you can add to the directory with your script to customize some of its behavior.
Executing Scripts at Timed Intervals: cron and at
In addition to the ability to construct convenient little (or arbitrarily large) programs of your own for the command line, Unix also provides a simple and powerful method for automatically running them at specific times when you want them to run. This method is embodied in the cron facility, which gives every user on the system a way to individually configure timing for executing arbitrary commands. The timing can be expressed in terms of minutes, hours, day of the week, day of the month, and month of the year. These parameters can be mixed and matched, allowing considerable flexibility in the specification of command timing.
For example, if you knew that your boss always wandered through the office looking over people's shoulders to see whether they're being productive on Monday mornings and Friday afternoons, you could configure a shell script to clean all the suspicious files off your desktop (swap in a clean ~/Desktop/ folder, and hide the other one), launch Word and Excel with some important-looking files, and hide iTunes, iChat, and your current favorite video game. So that you don't forget to run it, you could configure cron to automatically execute it at 9:00 a.m. on Mondays, and 1:00 p.m. on Fridays. If you're bad at remembering to copy important files from your desktop to your laptop before leaving work, you could use cron to schedule a snapshot of your desktop Documents folder and copy it to your laptop every workday afternoon at 4:30 p.m.. Although it might be more useful to schedule a reminder in iCal, you could even remind yourself to file your tax return by configuring cron to automatically launch Safari, pointed at the TurboTax website, on April 14th every year. Apple extensions to the standard Unix cron facility allow you to selectively prevent scheduled commands from running when a laptop is operating on battery power, and to schedule a command execution to occur after reboots, regardless of time, day, or date.
In addition to scheduling regularly occurring events, the cron facility can be used to schedule events that need to occur at a single specific time. To do this, the list of events and times are stored in a file, and a special cron job periodically checks the file to see when and if anything needs to be run in the near future. Finally, the same facility can be used to check the system load, instead of the time, and to hold execution of particular jobs until the system load is low and more CPU can be devoted to the task.
To access the time/day/date scheduling facility, you use the crontab command. The crontab command edits files (unsurprisingly called crontabs), that contain per-user scheduling information, and the always-running cron system reads these file and acts on them accordingly. The crontabs live in /var/cron/tabs/ in files named after each user, and are in a human-readable standardized format used by all Unix versions of cron (although they should not be edited by hand). Invoking the crontab command opens the file belonging to your user, in the command-line editor of your choice (or at least the one specified by your VISUAL or EDITOR environment variable). When the file is open, you can edit its content just as you normally would with that editor. When you quit out of the editor, your crontab file is saved, and the cron system is informed of the changes so that it can begin working with them.
All this probably sounds far more complicated than it is in reality. Sophisticated crontab schedules are built up in little uncomplicated bits, just like complicated Unix shell commands. For example, if you have a program named backup that you would like to run at 4:45 every afternoon, you'd run the crontab command, and edit the (possibly empty) crontab it presents you with to contain a line like this:
45 16 * * * backup
Positionally, this specifies the time you at which you want to fire the rule in the following form:
minute hour day-of-month month day-of-week <command>
Run the backup command on the 45th minute of the 16th hour of the day (counting from midnight as zero). The * characters indicate that these are "don't care" values, so the rule will fire on any day of the month, any month of the year, and any day of the week.
Perhaps this is a work machine and you'd only want it to run (and expend drive space making backups) on work days. You could limit it to only running Monday through Friday like this:
45 16 * * 1,2,3,4,5 backup
Sunday is the zeroth day (or the seventh day, either are acceptable syntax), so this runs your backup command at the 45th minute of the 16th hour of the first (Monday), second, third, fourth, and fifth days of the week.
Perhaps you're a school teacher and it makes sense to run this only while school is in session from September to June:
45 16 * 9-12,1-6 1,2,3,4,5 backup
Now it runs on the 45th minute of the 16th hour of weekdays, in months that are in the range September to December or January to June.
Finally, Apple has extended the crontab syntax to allow you to prevent a rule from firing if the computer is currently running on battery power (as a laptop might). If you need this additional flexibility, you simply prepend @AppleNotOnBattery to the command section and separate it from the command by a space:
45 16 * 9-12,1-6 1,2,3,4,5 @AppleNotOnBattery backup
There are additional, still more sophisticated ways to specify scheduling options available, and they are mentioned in the command documentation table for crontab (see Table 15.12). Most of these, such as the ability to specify a counting base for ranges (for example, do <command> on any minutes in the range 10-45, counting by 7s) are rather esoteric in purpose, and won't see extensive use at the hands of most users.
Although crontab files allow the scheduling of repeating events, they're not well suited for scheduling something that you want to happen once. For this situation, there is that at command. The at command schedules something to happen at some particular time.
The syntax for using at commands is simple: at <time> <command>. For example, if you really need to send a friend a copy of a file you've been working on before going home for the day, but you're worried that you'll forget to do it, you can write a short shell script that can do the mailing (mailfred), and then set up an at command like this, to fire it off in the afternoon at 4:45:
at 04:45pm mailfred
So long as you've configured root's crontab with atrun, that should fire off your mailfred script at about 4:45 p.m.. If you'd like to run it on a particular date, instead of simply the next 4:45 p.m. that comes around, you can use month, day, and, optionally, year specifiers as well. January 14th at 4:45 p.m. would look like this:
at 04:45pm jan 14 mailfred
If you're really thinking ahead, you can make it run January of 2008, if you like:
at 04:45pm jan 14 2008 mailfred
There are additional less-used options for specifying the at time, such as the ability to put the trigger into various queues that control the priority level of the job when it runs, and that let you specify times in silly increments, such as running at "teatime" (which means 4:00 p.m.), as well as different formats in which the time and date can be specified. These are discussed in the command documentation table for at (see Table 15.13).
|< Day Day Up >|