cron is a mechanism in Linux to run certain apps and/or tasks at certain moments in time. You have to see it very broad: in time means at every moment of the hour, day, week, month, year and so on.
It's a very flexible system that can run a task once a year but also every even or odd minute of every hour of every day of every week of every month of every year!
cron is controlled by a file called crontab.
cron is the name of the utility that can schedule jobs; Cron is a daemon which runs at the times of system boot. Cron comes from chron, the Greek prefix for "time".
Crontab "CRON TABle" is a file which contains the schedule of cron entries to be run and at specified times. File location varies by operating systems.
Cron job or cron schedule: is a specific set of execution instructions specifying day, time and command to execute. crontab can have multiple execution statements.
Linux has separate crontab files for every regular and root user. Based on how the crontab editor is invoked, Linux is editing the root or user crontab file
To open/edit the crontab file as user, run the command crontab -e, where -e means editing the crontab file
To open/edit the crontab file as root, run the command sudo crontab -e, where -e means editing the crontab file
When you edit the crontab file using crontab -e for the very first time you will see an empty file, only containing some comment. It's very useful to read the comment since this explains in short what different parameters crontab needs to run a task at a certain moment in time (repeating it if needed).
Basically, the crontab has the following fields that must be defined:
minute (m)
hour (h)
day of month (dom)
month (mon)
day of week (dow)
command to run (command)
It is represented like this in the crontab file:
# m h dom mon dow command
A * means at every moment for the given item. So, * * * * * means the command(s) given will run every minute, 24/7.
Intervals can be given to define what minute, hour, day of month and so on a command must be run.
Example:
*/2 * * * * <command> means run the given command every 2 minutes, so at :00, :02, :04,...
5/2 * * * * <command> means every 2 minutes starting from minute 5 after the hour, so at :05, :07, :09, :11,...
* 5/2 * * * <command> means every 2 hours starting from hour 5 after midnight, so at 5am, 7am, 9am, 11am, 1pm,...
A nice but simple website to test your crontab settings can be found here.
To test it out with more detailed information and help given, you can find another website here.
Depending on how you edit the crontab file (as regular user or sudo) you have to pay attention on how commands are started.
If a command needs sudo to run and you're editing the "regular user" crontab file then you also have to add sudo in the command. Editing the file as sudo doesn't need sudo in the command line.
Commands can be given in two ways:
Single command: this is the easiest and most straightforward way of giving a cron task.
Multiple commands: when you need multiple commands for a given cron task things get a little bit more complex since multiple commands can have dependencies on each other or not.
The 3 possible ways to separate multiple commands in the crontab file are:
;
When separated this way then commands are started sequentially one after the other without taking into account the result of the previous command (success or failed)
Example:
0 2 * * * chmod -R 755 /var/www/myapp; chmod -R 777 /var/www/myapp/logs
Here we first change the permission to 755 (recursively) for the given directory /var/www/myapp and then we modify the permission to 777 (recursively) for the /var/www/myapp/logs directory and everything below, irrespective of the success/failure of the previous command.
Note: this command is run every day at 2am, 24/7
&&
When separated this way then the next command will only run if the previous command was successful. The first failing command in a command chain will stop the remaining commands in the chain from starting up.
So, if you have commands that only should be started if all the previous commands were successful, this is the way to go.
Example:
0 0 3 * * cd /backup && bash backup.sh
Here you want to run a backup script only if the change to the /backup directory was successful.
Note: this command is run every 3rd day of the month at midnight.
||
When separated this way the next command is going to be executed only if (one of the previous) command(s) has failed.
Example:
02/10 0 7 * * [ -f /backup/mydb-`date +%F`.sql ] || echo "Today's backup file not found"
Here we will print the echo only if the first command failed.
Note: this command will run every 7th of the month during midnight hour only at :02, :12, :22, :32, :42, :52 minutes.
Although not standardised, the following shortcuts can be used instead of their longer counterparts:
@hourly: starts the crontab job every hour.
Same as 0 * * * * <command>
@daily: starts the crontab job at midnight every day.
Same as 0 0 * * * <command>
@weekly: starts the crontab job every week at midnight on Sunday.
Same as 0 0 * * 0 <command>
@montly: starts the crontab job at midnight every first day of the month.
Same as 0 0 1 * * <command>
@yearly: starts the crontab job at midnight every first day of the year.
Same as 0 0 1 1 * <command>
Note: @annually is an alias for @yearly
@reboot: starts the crontab job only when the system reboots.
Again, note that those are not standard shortcuts and your Linux distribution might not support those.
Depending on the Linux system used (Debian based or whatever) the crontab log file is /var/logs.
For Debian based distro's like the RPi, the log file is /var/log/systemlog.
To follow the logfile, use the following command: tail -f /var/log/syslog. It will show you the last 10 lines of the file and update it in realtime and you will see what cron has done so far.
Nice explanation on how to see the cron logfile and composing its content can be found here.
Very good answer on StackExchange serverfault.com about why things are not moving the way you want in cron can be found here.
It is possible to start and stop cron. Using systemd the following command will:
start cron: sudo service cron start
stop cron: sudo service cron stop
check the cron status: sudo service cron status
restart cron: sudo service cron restart