< 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.

Table 15.12. The Command Documentation for the crontab Command, and the Basic Format of a crontab File


Maintains crontab files for individual users.

crontab [-u <user>] <file>

crontab [-u <user>] [-l | -r | -e]

crontab is the program that installs, removes, and lists the tables the cron facility executes for users. Each user can have his own crontab, which is stored in /var/cron/tabs/ by username. These files are not to be edited directly.

If /var/cron/allow exists, the <user> trying to use cron, or that was specified to run the command in the crontab, must be listed in /var/cron/allow to be able to use cron. If /var/cron/allow does not exist, but /var/cron/deny exists, <user>s listed in /var/cron/allow cannot use the cron facility. If neither file exists (depending on site-dependent configuration), either only the super user may use this command or all users may be able to use this command.

The first form of the command installs a crontab from <file> or standard input if - is given instead of <file>. The second form of the command displays, removes, or edits the installed crontab.

-u <user>

Specifies the name of the user. If not specified, the user issuing the command is assumed. If crontab is being used inside an su or sudo command, -u should be specified to reduce confusion regarding whose crontab to edit.


Lists the current crontab on standard output.


Removes the current crontab.


Edits the current crontab using the editor specified by the environment variables VISUAL and EDITOR. On exiting the editor, the modified crontab is automatically installed.

The basic format of an in-crontab scheduling statement looks like this:

minute hour day-of-month month day-of-week [<user>] <command>

The valid ranges for the time specifiers are as follows (Sunday may be 0 or 7):

0-59 0-23 1-31 1-12 0-7

Fields may be separated by spaces or tabs. * may be used as the value of a field to mean all possible values for that field. A field value may be further specified by providing a single value, a comma-separated list of values, a range of values, or a comma-separated list of single values or ranges of values.

Step values may be specified by use of <range>/<number>. For example, 0-23/2 would specify every other hour. 0-23/2 is equivalent to the value list 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22. Step values may also be specified by */<number>. For example, every other hour could also be specified by */2 in that field.

Names may also be used for the month and day-of-week fields. Names are the first three characters of the actual name. Case does not matter. Lists or ranges of names, however, may not be used.

The <user> field is specified only in a system (root user) crontab.

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.


Use of the at command, or the related batch command, requires that that root have a specific command (the atrun command) configured in root's crontab. Without this command, at will schedule events, but they will never actually fire. To configure atrun for root, insert a line into root's crontab that contains the following:

 */10 * * * * root /usr/libexec/atrun 

sudo crontab -u root -e should get you editing the right crontab file.

This is not configured by default because including it will force your system to access the at files once every 10 minutes, and prevent things such as drive sleep from functioning properly. You can change the /10 stepping to something finer, or less-fine grained, if you like. With /10, at's precision is to the nearest following 10-minute mark a job scheduled for 4:45 will fire at 4:50. One scheduled at 2:29 will fire at 2:30, and so on.

Also be aware that although root is always able to run at jobs, the privileges for normal users are controlled by a pair of allow/deny files for the system and might not have permission to schedule at jobs, depending on the system configuration. The default on Mac OS X is to allow all users access.

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).

Table 15.13. The Command Documentation Table for at, atq, atrm, and batch


Executes commands at a specified time.


Lists the user's pending jobs, unless the user is super user. If the user is super user, lists all users' jobs.


Deletes jobs.


Executes commands as soon as system load levels permit. This is either when the average load drops to below 1.5 or the value specified at the invocation of atrun.

Using any of these commands requires the configuration of the atrun command in root's crontab.

at [-q <queue>] [-f <file>] [-m] <time>

atq [-q <queue>] [-v]

atrm [-q <queue>] <job> [<job2>...]

batch [-f <file>] [-m]

Both at and batch take input from either standard input or the file specified by -f option. The working directory, environment (except for the variables TERM, TERMCAP, DISPLAY, and _) and umask are retained from the time of invocation. Any at or batch command invoked from an su shell retains the current user ID.

Permission to use these commands depends on the files /var/at/at.allow and /var/at/at.deny. The super user may use these commands. If /var/at/at.allow exits, only the users (one per line) listed in the file may use these commands. If /var/at/at.allow does not exist, /var/at/at.deny is checked. Users listed in /var/at/at.deny may not use these commands. If an empty /var/at/at.deny exists, all users may use these commands. If neither file exists, only the super user may use these commands.

-q <queue>

Uses the specified queue. A queue consists of a single letter. Valid queue ranges are a to l. The a queue is the default, and b is the batch queue. Queues with higher letters run with increased niceness. If atq is given a specific queue, it shows only the pending jobs in the specified queue.

-f <file>

Executes commands in the specified <file> rather than from standard input.


Sends mail to the user when the job is complete, whether or not there was any output.


For atq, shows completed, but not yet deleted, jobs in the queue. Otherwise, shows the time the job will be executed.


<time> may be given in a variety of formats. Times may be of the form <HHMM> or <HH:MM> for a specific time of day. If the time has already passed, the next day is assumed. You may also specify midnight, noon, or teatime (teatime for 4:00 p.m.). You may also append AM, am, PM, or pm to a specific time. A time may also include a date in any of the following forms: <month-name> <day> [<year>], MMDDYY, MM/DD/YY, or DD.MM.YY. The date must follow the time specification. Time may also be given in increments, such as <now> + <count><time_units>, where <time_units> can be minutes, hours, days, or weeks. Terms today and tomorrow may also be used.

     < Day Day Up > 

    Mac OS X Tiger Unleashed
    Mac OS X Tiger Unleashed
    ISBN: 0672327465
    EAN: 2147483647
    Year: 2005
    Pages: 251 © 2008-2017.
    If you may any questions please contact us: