This is a Canonical Question about using cron & crontab.

You have been directed here because the community is fairly sure that the answer to your question can be found below. If your question is not answered below then the answers will help you gather information that will help the community help you. This information should be edited into your original question.

The answer for 'Why is my crontab not working, and how can I troubleshoot it?' can be seen below. This addresses the cron system with the crontab highlighted.

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.

up vote 276 down vote accepted

How to fix all of your crontab related woes/problems (Linux)

This is a community wiki, if you notice anything incorrect with this answer or have additional information then please edit it.

First, basic terminology:

  • cron(8) is the daemon that executes scheduled commands.
  • crontab(1) is the program used to modify user crontab(5) files.
  • crontab(5) is a per user file that contains instructions for cron(8).

Next, education about cron:

Every user on a system may have their own crontab file. The location of the root and user crontab files are system dependant but they are generally below /var/spool/cron.

There is a system-wide /etc/crontab file, the /etc/cron.d directory may contain crontab fragments which are also read and actioned by cron. Some Linux distributions (eg, Red Hat) also have /etc/cron.{hourly,daily,weekly,monthly} which are directories, scripts inside which will be executed every hour/day/week/month, with root privilege.

root can always use the crontab command; regular users may or may not be granted access. When you edit the crontab file with the command crontab -e and save it, crond checks it for basic validity but does not guarantee your crontab file is correctly formed. There is a file called cron.deny which will specify which users cannot use cron. The cron.deny file location is system dependent and can be deleted which will allow all users to use cron.

If the computer is not powered on or crond daemon is not running, and the date/time for a command to run has passed, crond will not catchup and run past queries.

crontab particulars, how to formulate a command:

A crontab command is represented by a single line. You cannot use \ to extend a command over multiple lines. The hash (#) sign represents a comment which means anything on that line is ignored by cron. Leading whitespace and blank lines are ignored.

Be VERY careful when using the percent (%) sign in your command. Unless they are escaped \% they are converted into newlines and everything after the first non-escaped % is passed to your command on stdin.

There are two formats for crontab files:

  • User crontabs

    # Example of job definition:
    # .---------------- minute (0 - 59)
    # |  .------------- hour (0 - 23)
    # |  |  .---------- day of month (1 - 31)
    # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |  |  |  |  |
    # *  *  *  *  *   command to be executed
  • System wide /etc/crontab and /etc/cron.d fragments

    # Example of job definition:
    # .---------------- minute (0 - 59)
    # |  .------------- hour (0 - 23)
    # |  |  .---------- day of month (1 - 31)
    # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
    # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
    # |  |  |  |  |
    # *  *  *  *  * user-name  command to be executed

Notice that the latter requires a user-name. The command will be run as the named user.

The first 5 fields of the line represent the time(s) when the command should be run. You can use numbers or where applicable day/month names in the time specification.

  • The fields are separated by spaces or tabs.
  • A comma (,) is used to specify a list e.g 1,4,6,8 which means run at 1,4,6,8.
  • Ranges are specified with a dash (-) and may be combined with lists e.g. 1-3,9-12 which means between 1 and 3 then between 9 and 12.
  • The / character can be used to introduce a step e.g. 2/5 which means starting at 2 then every 5 (2,7,12,17,22...). They do not wrap past the end.
  • An asterisk (*) in a field signifies the entire range for that field (e.g. 0-59 for the minute field).
  • Ranges and steps can be combined e.g. */2 signifies starting at the minimum for the relevant field then every 2 e.g. 0 for minutes( 0,2...58), 1 for months (1,3 ... 11) etc.

Debugging cron commands

Check the mail! By default cron will mail any output from the command to the user it is running the command as. If there is no output there will be no mail. If you want cron to send mail to a different account then you can set the MAILTO environment variable in the crontab file e.g.

1 2 * * * /path/to/your/command

Capture the output yourself

1 2 * * *  /path/to/your/command &>/tmp/mycommand.log

which captures stdout and stderr to /tmp/mycommand.log

Look at the logs; cron logs its actions via syslog, which (depending on your setup) often go to /var/log/cron or /var/log/syslog.

If required you can filter the cron statements with e.g.

grep CRON /var/log/syslog 

Now that we've gone over the basics of cron, where the files are and how to use them let's look at some common problems.

Check that cron is running

If cron isn't running then your commands won't be scheduled ...

ps -ef | grep cron | grep -v grep

should get you something like

root    1224   1  0 Nov16 ?    00:00:03 cron


root    2018   1  0 Nov14 ?    00:00:06 crond

If not restart it

/sbin/service cron start


/sbin/service crond start

There may be other methods; use what your distro provides.

cron runs your command in a restricted environment.

What environment variables are available is likely to be very limited. Typically, you'll only get a few variables defined, such as $LOGNAME, $HOME, and $PATH.

Of particular note is the PATH is restricted to /bin:/usr/bin. The vast majority of "my cron script doesn't work" problems are caused by this restrictive path. If your command is in a different location you can solve this in a couple of ways:

  1. Provide the full path to your command.

    1 2 * * * /path/to/your/command
  2. Provide a suitable PATH in the crontab file

    1 2 * * * command 

If your command requires other environment variables you can define them in the crontab file too.

cron runs your command with cwd == $HOME

Regardless of where the program you execute resides on the filesystem, the current working directory of the program when cron runs it will be the user's home directory. If you access files in your program, you'll need to take this into account if you use relative paths, or (preferably) just use fully-qualified paths everywhere, and save everyone a whole lot of confusion.

The last command in my crontab doesn't run

Cron generally requires that commands are terminated with a new line. Edit your crontab; go to the end of the line which contains the last command and insert a new line (press enter).

Check the crontab format

You can't use a user crontab formatted crontab for /etc/crontab or the fragments in /etc/cron.d and vice versa. A user formatted crontab does not include a username in the 6th position of a row, while a system formatted crontab includes the username and runs the command as that user.

I put a file in /etc/cron.{hourly,daily,weekly,monthly} and it doesn't run

  • Check that the filename doesn't have an extension see run-parts
  • Ensure the file has execute permissions.
  • Tell the system what to use when executing your script (eg. put #!/bin/sh at top)

Cron date related bugs

If your date is recently changed by a user or system update, timezone or other, then crontab will start behaving erratically and exhibit bizarre bugs, sometimes working, sometimes not. This is crontab's attempt to try to "do what you want" when the time changes out from underneath it. The "minute" field will become ineffective after the hour is changed. In this scenario, only asterisks would be accepted. Restart cron and try it again without connecting to the internet (so the date doesn't have a chance to reset to one of the time servers).

Percent signs, again

To emphasise the advice about percent signs, here's an example of what cron does with them:

# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

will create the ~/cron.out file containing the 3 lines


This is particularly intrusive when using the date command. Be sure to escape the percent signs

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"
  • May want to also mention in the 'restricted env' section that LD_LIBRARY_PATH may also need to have any additional directories set in case your cron task is failing on account of being unable to find shared libraries. – DavidJ Jun 23 '15 at 13:10
  • note that you even can write something like this: 35 1,5-23/2 * * * do_something instead of 35,1,5,7,9,.. * * * Additionally this translates the entries you make to human language. – Dennis Nolte Apr 22 '16 at 13:43
  • The output capture does not work for me, may be because of the sh shell. I think this is more portable: ... /path/to/your/command >/tmp/mycommand.log 2>&1 – chus Aug 2 '16 at 14:24
  • this worked for me: sudo apt-get install postfix – jmunsch Aug 2 '17 at 3:07
  • does cron job also depends on how heavy is the file? Because I ran simple hello world in python with cron, it worked. But my second code was a bit heavy and normally do run but with cron it is not giving any output into the file. – Devendra Bhat Apr 10 at 6:19

If your cronjobs stop working, check that your password hasnt expired., since once it has, all cron jobs stop.
There will be messages in /var/log/messages similar to the one below which show issues with authenticating the user:

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)

  • 2
    Just got this as well (error message file /var/log/syslog for me). In my case a DigitalOcean box that, at create time, they reset the root password (optionally) to another one, and apparently until you go in there and change it, all the cron jobs don't run. Bummer. Fix is something like sudo -u root passwd – rogerdpack Apr 1 '16 at 16:13

Debian Linux and its derivative (Ubuntu, Mint, etc) have some peculiarities that may prevent your cron jobs from executing; in particular, the files in /etc/cron.d, /etc/cron.{hourly,daily,weekly,monthly} must :

  • be owned by root
  • only be writable by root
  • not be writable by group or other users
  • have a name without any dots '.' or any other special character but '-' and '_' .

The last one hurts regularly unsuspecting users; in particular any script in one of these folders named,,, etc. will not be executed, ever.

In my experience, this particular point has been by far the most frequent reason for a non-executing cronjob on Debian and derivatives.

See man cron for more details, if necessary.

Uncommon and irregular schedules

Cron is all things considered a very basic scheduler and the syntax does not easily allow an administrator to formulate slightly more uncommon schedules.

Consider the following job which commonly would be explained to "run command every 5 minutes":

*/5 * * * * /path/to/your/command


*/7 * * * * /path/to/your/command

which does not always run command every 7 minutes.

Remember that the / character can be used to introduce a step but that steps don't wrap beyond the end of a series e.g. */7 which matches every 7th minute from the minutes 0-59 i.e. 0,7,14,21,28,35,42,49,56 but between one hour and the next there will be only 4 minutes between batches, after 00:56 a new series starts at 01:00, 01:07 etc. (and batches won't run on 01:03 , 01:10 , 01:17 etc.).

What to do instead?

Create multiple batches

Rather than a single cron job, create multiple batches that combined result in the desired schedule.

For instance to run a batch every 40 minutes (00:00, 00:40, 01:20, 02:00 etc.) create two batches, one that runs twice on the even hours and second one that runs only the odd hours:

# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

Run your batches less frequently

Rather than running your batch every 7 minutes, which is a difficult schedule to break down in multiple batches, simply run it every 10 minutes instead.

Run your batches more frequently

Many odd schedules evolve because the batch runtimes increase/fluctuate and then the batches get scheduled with a bit of additional safety margin to prevent subsequent runs of the same batch from overlapping and running concurrently.

Instead, think differently and create a cronjob that will fail gracefully when a previous run has not finished yet, but which will run otherwise. See this Q&A:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job --minutely

On a similar note, you can let you batch record the timestamp of the last successful run and at the start of the batch check if the desired interval between batches has already passed and execute and otherwise exit gracefully.

In bash the seven-minute-job would look something like something like:

# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
    echo "The minimum interval of 7 minutes between successive batches hasn't passed yet."

echo "Start running your batch"

date > /tmp/lastrun

Which you can then safely (attempt) to run every minute:

* * * * * /path/to/your/seven-minute-job

Don't use cron

If your needs are complex you might consider using a more advanced product that is designed to run complex schedules (distributed over multiple servers) and that supports triggers, job dependancies, error handling, retries monitoring etc. The industry jargon would be "enterprise" job scheduling and/or "workload automation".


If you have some cron job like:

php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log

And in case of errors expect, that they will be sent to you, but they not -- check this.

PHP by default not sending errors to STDOUT. @see

To fix this, add in cli`s php.ini or in your line (or in your's bash wrapper for PHP) these:

  • --define display_startup_errors=1
  • --define display_errors='stderr'

1st setting will allow you to have fatals like 'Memory oops' and 2nd -- to redirect them all to STDERR. Only after you can sleep well as all will be sent to your root's mail instead of just logged.

  • 2
    That error report was closed back in 2007 with the status of the patch being added to the PHP 5.2+ branches. Are you sure this is needed? I just tried on PHP 5.4 and it seems to work fine. (It is still needed for PHP 4 though). – Xeoncross Mar 5 '14 at 20:34
  • @Xeoncross see date of answer :) – gaRex Mar 6 '14 at 3:09
  • 1
    Yes, that is what confused me since you answered in 2013 and the ticket was back in '07. – Xeoncross Mar 6 '14 at 4:55

protected by voretaq7 Oct 9 '13 at 16:35

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.