Command scheduling with cron

Posted by Steve on Mon 13 Dec 2004 at 19:25

Many pieces of system administration can be automated via perl scripts, or shell scripts which run at regular intervals. For example you might have a script to check that your disk isn't full which runs once an hour - informing you if there are problems. The most common mechanism for scheduling commands on Unix systems is via the cron package. This allows users to schedule arbitary commands to run at arbitary times with regular frequency.

In Debian the cron package is installed as part of the base system, and will be running by default.

Cron, as supplied in Debian, has two purposes:

  • To run system jobs on a daily/weekly/monthly basis
  • To allow users to setup their own schedules

The system schedules are setup when the package is installed, via the creation of some special directories:

/etc/cron.d
/etc/cron.daily
/etc/cron.hourly
/etc/cron.monthly
/etc/cron.weekly

Except for the first one which is special, these directories allow scheduling of system-wide jobs in a coarse manner. Any script which is executable and placed inside them will run at the frequency which its name suggests.

For example if you place a script inside /etc/cron.daily it will be executed once per day, every day.

The time that the scripts run in those system-wide directories is not something that an administration typically changes, but the times can be adjusted by editing the file /etc/crontab. The format of this file will be explained shortly.

The normal manner which people use cron is via the crontab command. This allows you to view or edit your crontab file, which is a per-user file containing entries describing commands to execute and the time(s) to execute them.

To display your file you run the following command:

crontab -l

root can view any users crontab file by adding "-u username", for example:

crontab -u skx -l  # List skx's crontab file.

The format of these files is fairly simple to understand. Each line is a collection of six fields separated by spaces.

The fields are:

  1. The number of minutes after the hour (0 to 59)
  2. The hour in military time (24 hour) format (0 to 23)
  3. The day of the month (1 to 31)
  4. The month (1 to 12)
  5. The day of the week(0 or 7 is Sun, or use name)
  6. The command to run

More graphically they would look like this:

*     *     *     *     *  Command to be executed
-     -     -     -     -
|     |     |     |     |
|     |     |     |     +----- Day of week (0-7)
|     |     |     +------- Month (1 - 12)
|     |     +--------- Day of month (1 - 31)
|     +----------- Hour (0 - 23)
+------------- Min (0 - 59)

(Each of the first five fields contains only numbers, however they can be left as '*' characters to signify any value is acceptible).

Now that we've seen the structure we should try to ru na couple of examples.

To edit your crontabe file run:

crontab -e

This will launch your default editor upon your crontab file (creating it if necessary). When you save the file and quit your editor it will be installed into the system unless it is found to contain errors.

If you wish to change the editor used to edit the file set the EDITOR environmental variable like this:

export EDITOR=/usr/bin/emacs
crontab -e

Now enter the following:

0   *   *   *   * /bin/ls

When you've saved the file and quit your editor you will see a message such as:

crontab: installing new crontab

You can verify that the file contains what you expect with :

crontab -l

Here we've told the cron system to execute the command "/bin/ls" every time the minute equals 0, ie. We're running the command on the hour, every hour.

Any output of the command you run will be sent to you by email, if you wish to stop this then you should cause it to be redirected, as follows:

0   *   *   *   *  /bin/ls   >/dev/null 2&>1

This causes all output to be redirected to /dev/null - meaning you won't see it.

Now we'll finish with some more examples:

# Run the `something` command every hour on the hour
0   *   *   *   * /sbin/something

# Run the `nightly` command at ten minutes past midnight every day
10  0   *   *   * /bin/nightly

# Run the `monday` command every monday at 2 AM
0   2   *   *   1  /usr/local/bin/monday

One last tip: If you want to run something very regularly you can use an alternate syntax: Instead of using only single numbers you can use ranges or sets.

A range of numbers indicates that every item in that range will be matched, if you use the following line you'll run a command at 1AM, 2AM, 3AM, and 4AM:

# Use a range of hours matching 1, 2, 3 and 4AM
*   1-4   *   *   * /bin/some-hourly

A set is similar, consisting of a collection of numbers seperated by commas, each item in the list will be matched. The previous example would look like this using sets:

# Use a set of hours matching 1, 2, 3 and 4AM
*   1,2,3,4   *   *   * /bin/some-hourly

 

 


Posted by Anonymous (127.0.xx.xx) on Mon 13 Dec 2004 at 21:06
Do you know any collection of scripts that can be used to automate various administrative tasks ?

[ Parent | Reply to this comment ]

Posted by Steve (127.0.xx.xx) on Mon 13 Dec 2004 at 21:09
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Shelldorado.com has a small collection of scripts - but most things I was thinking of were site-specific.

Cleaning out /tmp, printing reports of the users who are using the most disk space, generating stats pages for a group of web hosts, etc.

If everything could be automated we'd be out of a job !

-- Steve.org.uk

[ Parent | Reply to this comment ]

Posted by Anonymous (195.220.xx.xx) on Tue 7 Jun 2005 at 13:44
There is a problem when inserting an unexcpeted special character, such as space or ,tab, in 'crontab -e'.

The messsage is:

/bin/sh: line 1: root: command not found silvere.

[ Parent | Reply to this comment ]

Posted by Anonymous (68.171.xx.xx) on Thu 8 Sep 2005 at 22:57
Shouldn't that be

| | | | +----- Day of week (0-6)

?

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Thu 8 Sep 2005 at 23:01
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Yes, I guess so.

Running :

man 5 crontab

shows:

field          allowed values
-----          --------------
minute         0-59
hour           0-23
day of month   1-31
month          1-12 (or names, see below)
day of week    0-7 (0 or 7 is Sun, or use names)

Steve
--

[ Parent | Reply to this comment ]

Posted by Anonymous (68.104.xx.xx) on Sat 4 Oct 2008 at 12:49
0 & 7 both = Sunday for some reason

[ Parent | Reply to this comment ]

Posted by Anonymous (130.239.xx.xx) on Wed 27 May 2009 at 21:24
I think it's because the week starts on Sunday in the US, but on Monday in most european countries.

[ Parent | Reply to this comment ]

Posted by Anonymous (67.38.xx.xx) on Mon 6 Feb 2006 at 20:17

Additionally you can make intervals:

*/15 * * * * /bin/example
* */2 * * * /bin/example2

This will run the example script every 15 minutes, and the example2 script every 2 hours.
Use the same syntax in differnt columns for similar effects.

[ Parent | Reply to this comment ]

Posted by Anonymous (82.211.xx.xx) on Wed 22 Mar 2006 at 08:54
When I need run my script every 2.4 hours (2 hours and 24 minutes), rightly this line?
24 */2 * * * /path/to/script
Or this:
*/24 */2 * * * /path/to/script
Thanks for your answer! [smportal.info]

[ Parent | Reply to this comment ]

Posted by Anonymous (62.163.xx.xx) on Sun 25 Jun 2006 at 14:50
Wouldn't that just be

/144 * /path/to/script

[ Parent | Reply to this comment ]

Posted by Anonymous (221.135.xx.xx) on Wed 11 Feb 2009 at 10:09
The minute field wont accept a value greater than 59! Any other alternative for running a job every 2.4 hours?

[ Parent | Reply to this comment ]

Posted by Anonymous (77.86.xx.xx) on Mon 10 Oct 2011 at 11:28
You need it to run 10 times a day (every 2.4 Hours).

So:
* * */10 * * Command to be executed

This means Every minute, of every hour, every day/10 - should work.

[ Parent | Reply to this comment ]

Posted by Anonymous (78.60.xx.xx) on Tue 17 Jun 2008 at 16:11
LOL don`t defraud peoples, i have wasted 2 days for find why so much "doubleposts".. It should be:
0 */2 * * * /bin/example2

[ Parent | Reply to this comment ]

Posted by JohnMG (72.1.xx.xx) on Thu 3 Aug 2006 at 19:21
[ Send Message ]
As root, is it preferable to edit /etc/crontab, or to instead use "crontab -e" (which will allow you to edit /var/spool/cron/crontabs/root)?

Seems redundant to have both (for root).

[ Parent | Reply to this comment ]

Posted by Steve (62.30.xx.xx) on Thu 3 Aug 2006 at 19:24
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Generally it is preferable to use "crontab -e" to edit the root crontab, since the /etc/crontab file is meant as a system file which isn't to be editted.

Whilst you may edit it if you wish you can see from the contents that it is responsible for running things in /etc/cron.daily, etc, so it seems most sensible to leave it alone. (Obviously you could put scripts into /etc/cron.*/ if you wanted them to run with the relevant frequency...)

Steve

[ Parent | Reply to this comment ]

Posted by daan (194.171.xx.xx) on Mon 27 Nov 2006 at 08:32
[ Send Message ]
What happens if the computer is switched off when a command is scheduled to run? Is it just skipped, or is it executed as soon as the computer is switched on again?

[ Parent | Reply to this comment ]

Posted by Steve (62.30.xx.xx) on Mon 27 Nov 2006 at 09:05
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Either could happen depending on your version of cron.

By default you'll have cron installed which will not start jobs which should have occurred whilst it was not running. If you install the anacron package then the jobs will run when the computer is turned on next.

Steve

[ Parent | Reply to this comment ]

Posted by Anonymous (89.82.xx.xx) on Sat 20 Jan 2007 at 22:57
is cron working with gui softwares too.
if not is there any aother tools for this kind of task.

[ Parent | Reply to this comment ]

Posted by Anonymous (203.13.xx.xx) on Tue 20 Mar 2007 at 03:23
The final examples about sets and ranges is a little misleading. The comment implies that it will run only on the hour, but the cron entry actually has it running every minute in those hours:

# Use a set of hours matching 1, 2, 3 and 4AM
* 1,2,3,4 * * * /bin/some-hourly

versus

# Use a set of hours matching 1, 2, 3 and 4AM
0 1,2,3,4 * * * /bin/some-hourly

[ Parent | Reply to this comment ]

Posted by Anonymous (91.142.xx.xx) on Tue 14 Aug 2007 at 22:23
Would 10,30,20 1,2,4 * * * /bin/script work?

[ Parent | Reply to this comment ]

Posted by Anonymous (68.3.xx.xx) on Fri 14 Sep 2007 at 01:57
I found this small note at the end of the man page for cron under BUGS.

"Although cron requires that each entry in a crontab end in a newline character, neither the crontab command nor the cron daemon will detect this error. Instead, the crontab will appear load normally. However, the command will never run. The best choice is to ensure that your crontab has a blank line at the end."

I was chasing this issue for over an hour - I could not figure out why the last cron job in crontab would not run! Just thought I would document it here so the next person does not loose sleep over this!

[ Parent | Reply to this comment ]

Posted by Anonymous (88.77.xx.xx) on Tue 2 Oct 2007 at 01:17
I just learned that a script in cron.daily was not executed because the name had an underscore in it!!! BEWARE OF THE SHORTSIGHTED UNIX PROGRAMMER!

[ Parent | Reply to this comment ]

Posted by Anonymous (68.174.xx.xx) on Wed 21 Nov 2007 at 05:22
Damn ! You made my day...

Neither dot in the file names...

automysqlbackup.sh users... BEWARE.

[ Parent | Reply to this comment ]

Posted by Anonymous (158.52.xx.xx) on Fri 23 Nov 2007 at 17:30
WOW

I am quite a newbie in Linux and I was crashing my head on the wall to understand why my cron scripts were not executed... damn it it's because I have dots in the filename!! Thank you for helping : )

[ Parent | Reply to this comment ]

Posted by Anonymous (70.232.xx.xx) on Sat 22 Dec 2007 at 03:28
Interesting!

I dont think any of mine are running!

I seem to have anacron installed also, I wonder if this is inteferring with cron.

[ Parent | Reply to this comment ]

Posted by Anonymous (165.21.xx.xx) on Tue 29 Jan 2008 at 21:18
Damned... i did not know why my script did not run... only after i read your comments... my script name contains underscore and dot ...

Thanks for your share...

[ Parent | Reply to this comment ]

Posted by Anonymous (117.20.xx.xx) on Thu 3 Apr 2008 at 01:10
I was also getting a sore head...crons would not run.
Was trying to run a .php file, has a . in the name.

Many thanks.

[ Parent | Reply to this comment ]

Posted by Windoze-Fanboi (63.227.xx.xx) on Tue 8 Apr 2008 at 19:22
[ Send Message ]
Indeed.

My cronjob named _.__....____.__.sh would not run either.

Now I know, and knowing is...

[ Parent | Reply to this comment ]

Posted by Anonymous (81.64.xx.xx) on Sun 4 May 2008 at 11:03
if i want to run once ?
if i want to run 10m after boot ?
@reboot, , .... ???

[ Parent | Reply to this comment ]

Posted by Anonymous (193.5.xx.xx) on Mon 4 Aug 2008 at 08:51
If you want to run once, why use cron?
If you still want to to this, you could either remove your own cronjob in the script. This gets complicated (crontab -l, piping and grep -v are your friends) or change your script that it only runs once.
For 10 minutes after boot, put it in the init.d/, fork it and put an sleep 600 in front.

@reboot, again init.d is your friend, specifically /etc/init.d/reboot

HTH, micha

[ Parent | Reply to this comment ]

Posted by Anonymous (70.131.xx.xx) on Wed 14 Oct 2009 at 21:21
if you don't have root access you can run a command at startup easily with crontab (@reboot) but not with init.d.

[ Parent | Reply to this comment ]

Posted by Anonymous (202.164.xx.xx) on Fri 8 Aug 2008 at 04:05
Ive made a script for it to run on vlc using playlists and i use .xsession for the vlc to play individually. problem is that when i chmod u+x my script:

my crontab -e
0 20 * * * /home/script/to/script1
1 20 * * * /home/script/to/script2
.xsession is:
vlc file:///home/user/to/path1

my script1 is:
echo "vlc file:///home/to/path2">; .xsession
kill -9 `pgrep vlc`
sleep 5
echo "vlc file:///home/user/to/path1">; .xsession

i would like to use my vlc file path 1 as my main playlist and then when the crontab hits the time, it will change to path 2. but when it restarts or shut off, my main will be seen thats why i do have another echo.

[ Parent | Reply to this comment ]

Posted by Anonymous (68.104.xx.xx) on Sat 4 Oct 2008 at 13:27
I feel really dense right now.

I'm trying to do this on a debian/GUN linux box logged into root. Cron is running pid=1608

crontab -e

#Insert line one below the headers

0-59 * * * * root echo "this is crap"

Leaving a blank line at the bottom and saving the file.

Should this not be spitting this is crap onto my screen every minute?

mroth@theitsystem.com

[ Parent | Reply to this comment ]

Posted by Steve (82.41.xx.xx) on Sat 4 Oct 2008 at 13:55
[ Send Message | View Steve's Scratchpad | View Weblogs ]

No.

There are two things wrong here:

You've specified "root" which you shouldn't ever do for a personal crontab entry - If you're editing a file via "crontab -e" you just need:

times command

It is only in the system crontab entries, such as /etc/cron.daily/ that you need specify a username.

Secondly the output of cron, if any, is mailed to you.

Take a look at the mail for root and you will most likely see it.

For a personal test I'd just use this:

0-59 * * * * /usr/bin/uptime >> /var/tmp/uptime.log

Steve

[ Parent | Reply to this comment ]

Posted by TheITSystem (68.104.xx.xx) on Sun 5 Oct 2008 at 01:58
[ Send Message | View TheITSystem's Scratchpad ]
Okay the crontab is working now.

I don't even know how I got it to work, but it's working.

Next and probably last question for this topic:

How do I update and/or replace a crontab using Perl? This might be a new topic, but I don't see new topic button anywhere.

[ Parent | Reply to this comment ]

Posted by Anonymous (195.229.xx.xx) on Sun 26 Apr 2009 at 19:30
how to exit from "crontab -e
> after
what we have to type to exit crontab command

[ Parent | Reply to this comment ]

Posted by Steve (2001:0xx:0xx:0xxx:0xxx:0xxx:xx) on Sun 26 Apr 2009 at 19:33
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Exit the editor and that is all - by default it is probably vim/vi so you can edit by typing "Escape :wq".

If you prefer a different editor run:

EDITOR=/usr/bin/joe crontab -e

Or similar.

Steve

[ Parent | Reply to this comment ]

Posted by Anonymous (58.96.xx.xx) on Fri 1 Apr 2011 at 03:56
The example you give to silence email output by redirecting stdout and stderr to null ( 0 * * * * /bin/ls >/dev/null 2&>1 ) seems to have a mistake.

As far as I'm aware, the second redirect *should* read 2>&1 (ampersand after the redirect symbol)

[ Parent | Reply to this comment ]

Posted by Anonymous (71.203.xx.xx) on Mon 30 Dec 2013 at 23:37
This still needs to be fixed

[ Parent | Reply to this comment ]

Posted by Anonymous (190.206.xx.xx) on Mon 29 Aug 2011 at 13:51
if i have a script "path/to/script" somewhere else, what file permissions should i use?

Thanks.

[ Parent | Reply to this comment ]

Posted by Steve (90.193.xx.xx) on Mon 29 Aug 2011 at 14:09
[ Send Message | View Steve's Scratchpad | View Weblogs ]

It must be executable. Typically that means "chmod 755 /path/to/script".

Steve

[ Parent | Reply to this comment ]

Posted by Anonymous (89.205.xx.xx) on Sun 1 Jul 2012 at 21:39
Need to do backup and Sunday full, on Wednesday in what has changed in terms of the week, other days only change compared to the previous day.
What is the syntax of the line to be added to / etc / crontab.?
Help: command date + "% A" print day of week (Monday, Tuesday .....).

[ Parent | Reply to this comment ]

Posted by Steve (90.220.xx.xx) on Sun 1 Jul 2012 at 21:42
[ Send Message | View Steve's Scratchpad | View Weblogs ]

Break it down into two steps:

# This job runs at midnight on Sundays only
0 0 * * 0 /path/to/script

# This job runs at 02:03 on Wednesday only
2 3 * * 3 /path/to/second/script

Steve

[ Parent | Reply to this comment ]

Posted by Anonymous (86.105.xx.xx) on Mon 12 Nov 2012 at 00:40
I get:
...: (root) CMD (/usr/bin/php /var/www/cronscripts/run.php^M)
...: (CRON) error (grandchild #21699 failed with exit status 1)

what could I (or other possible future people who read this forum and have this problem) do?

[ Parent | Reply to this comment ]

Posted by matteosistisette (77.231.xx.xx) on Sat 30 Nov 2013 at 22:32
[ Send Message ]
Where do you set up the email address to which the output is sent? It would be nice if you mentioned this in the article.

[ Parent | Reply to this comment ]

Posted by Steve (2.125.xx.xx) on Sat 30 Nov 2013 at 23:19
[ Send Message | View Steve's Scratchpad | View Weblogs ]

This is discussed in "man 5 crontab". In short you add this to the top of your file:

MAILTO=steve@example.com

This assumes your system will send outgoing mail correctly though, if not don't set such at thing and the mail will go to the appropriate local user-account. (Probably in ~/Maildir, or beneath /var/spool/mail.)

Steve

[ Parent | Reply to this comment ]

Sign In

Username:

Password:

[Register|Advanced]

 

Flattr

 

Current Poll

Which init system are you using in Debian?






( 1057 votes ~ 6 comments )