Project 71. Schedule Commands with cron"How do I schedule a shell script to run at 8:30 every morning so my boss will think I arrive at work on time?" This project uses the Unix cron daemon and the crontab command to schedule jobs to be run at periodic intervals. It shows you how to schedule both system jobs and jobs that belong to individual user accounts. Project 70 covers one-off scheduling with the at command. Project 72 covers periodic maintenance controlled by Apple's Launch Daemon. Schedule a JobThe cron daemon is automatically enabled in a default Mac OS X installation. It runs continually and each minute checks its schedules (crontabs) to see whether any jobs are ready to run. When a job has been run, it's not removed from the schedule but remains to be executed at the next occurrence of the specified interval. We might schedule a job to run at a specific time, such as 8:30 a.m. every day, or every Monday, or on the first of every month. To schedule jobs with cron, you need only edit or create a crontab specifying what to run and when to run it. Each user can create her own crontab; additionally, cron supports a system crontab in a file maintained by the root user. Let's test cron by scheduling a simple command that creates the file /cron-on. We'll look at adding jobs to the system crontab first and then consider user crontabs. Here's what the system crontab looks like (it's empty except for comments that start with a # character). $ cat /etc/crontab # The periodic and atrun jobs have moved to launchd jobs # See /System/Library/LaunchDaemons # # minute hour mday month wday who command
The last line is there to remind you of the required format of each job you add. We schedule a job by adding a line to this file, entering an appropriate value in each column to specify the time and date on which the job will be run, which user the job should be run as, and the job itself. The job may be a command written directly to the crontab or the filename of a shell script to execute. Edit the system crontab file /etc/crontab, using a Unix text editor such as nano. Because the root user owns the system crontab file, we must issue the command by using sudo and give an administrator password when prompted. $ sudo nano /etc/crontab Password: Learn More
Choose a suitable time in the near future, and add a line such as the one shown in the following output. You may separate columns with spaces or tabs. $ cat /etc/crontab ... # minute hour mday month wday who command 30 15 * * * root /usr/bin/touch /cron-on We scheduled our simple job to run at 15:30 hours. The three date columns contain stars, which are taken to mean every. Our job will be run at 15:30 every day. The job will be run as user root, executing the command /usr/bin/touch /cron-on. At the designated time, the file /cron-on should be created. If you were to delete the file by typing $ sudo rm /cron-on it would be recreated tomorrow at 15:30. To cancel the job, edit the file /etc/crontab, and remove the line you just added. Capture Output from a JobWhen a job is executed, output is captured and mailed to you. Use the Unix mail command to view it, or simply view the mail directly with a text editor; you'll find it in a file called /var/mail/your-user-name. To throw away all output, redirect standard output and standard error to /dev/null by appending &> /dev/null to the end of the command. To run a backup script and throw away all output, including errors written to standard error, we might add a line such as 30 20 * * * root /usr/local/sbin/backup-script &>/dev/null Learn More
Tip
To redirect output to a file, append &> cron.out (or any other filename) to the end of the command. We might execute the date command, for example, and write the output to the file cron-date in the user's home directory. Note that in this case, we requested that the job be run as user saruman; consequently, the file will be written to that user's home directory and will be owned by saruman. 30 15 * * * saruman date &> ~/cron-date Tip
Specify DatesHere are some more examples that specify a time and date on which to launch a job. Run job1 at 4:30 in the morning every Saturday. 30 4 * * 6 root job1 Run job2 at 5:30 in the morning on the first of each month. 30 5 1 * * root job2 The time fields can be more complex than simple numbers. To run job3 at 11 a.m., 4 p.m., and 8 p.m., use 0 11,16,20 * * * root job3 Tip
To run job3 every n minutes, or hours, or days, and so on, use the notation */n in the appropriate column. To run job3 every 10 minutes, we might specify */10 * * * * root job3 In place of the five number fields, cron can interpret special strings like "@weekly" to mean "once a week." User CrontabsYou can maintain your own personal crontab. The format of its job line is the same as the system crontab's, except the who field is omitted; you may run a job only as yourself. Use the crontab command to define your crontab. I recommend that you maintain your crontab schedule in a file. You can edit the file whenever you want to change the cron schedule and then load the file into your personal crontab whenever it's changed. Note
Let's create such a file. We'll specify a single job that executes the date command every minute, writing the current time and date to the file ~/user-crontest. Here's our file. $ cat my-crontab */1 * * * * date &>~/user-crontest Now load the file into your crontab by typing $ crontab my-crontab To examine our crontab, type $ crontab -l */1 * * * * date &>$HOME/user-crontest To delete (remove) it, type $ crontab -r |