I have been using crons for a while now but I always wanted to spend some time reading about them or creating one from scratch so that I could fully understand what is a cron. This post is exactly that, notes on creating my first cron and what I’ve learned during the process.
I am working on Linux Ubuntu 22.04.02 so some of the things/commands/logs you’ll see in this post may be different if you are using another system.
What is a cron?
The name cron originates from the Greek word hronos (Greek χρόνος), which means time. Υou may also know the word as Chronos or Kronos, who was the god of time and king of the Titans in Greek mythology.
A cron is a daemon, meaning it is a process — an instance of a program — that runs continuously in the background of a Unix-like operating system. It usually starts along with the system and stops when the system shuts down.
Daemon process names are suffixed with the letter d to denote that we are referring to a daemon. That’s why you might see a cron also mentioned as crond, instead of just cron.
A typical cron day
If a cron runs continuously, what does it do while running?
📆 A cron’s typical day would probably look something like this:
For each minute of every day
- Check if you have anything to do now, this minute.
- If you have something to do, do it.
- Get back to sleep for one minute.
- Wake up and go back to step 1.
Now we are getting somewhere, so it is a process that checks every minute if it has something to do, at that specific minute. But where does it live? Can we see it?
Let’s open our terminal and type
sudo systemctl status cron.service
Bashℹ️ systemctl
command is a utility – a helper command – which helps us control the systemd
, the system daemon. (ctl
suffix stands for control)
ℹ️ systemd
– is a system daemon that is used to manage other daemons.
So basically, what we are trying to do through this command is ask a manager daemon to show us the status of our cron service. Executing it shows the following information:
● cron.service - Regular background program processing daemon
Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: >
Active: active (running) since Sat 2023-06-10 09:55:40 EEST; 3 days ago
Docs: man:cron(8)
Main PID: 981 (cron)
Tasks: 1 (limit: 38136)
Memory: 1.1M
CPU: 1.491s
CGroup: /system.slice/cron.service
└─981 /usr/sbin/cron -f -P
BashSay hello to this little process inside your system! This is a cron!
(That reminds me of a famous Al Pacino quote… 😎)
There is a lot of info in this message, and I am not quite familiar with the terminology. What is important for now is that this is about our cron.service
which is a Regular background program processing daemon currently
in active
state and running since Sat 2023-06-10 09:55:40 EEST
.
Excellent! We now know what a cron looks like and how it spends its days.
Using a cron to do our work
A cron can be set to do whatever you can imagine! Ooh strong word, right? 😯 Examples, please? Fair enough… 🤓
You could use a cron to:
- Send emails to your clients.
- Have a backup for specific files in your system.
- Remind yourself of a specific task you have to do.
- Assign a cron to do heavy-duty work when your machine’s resources are used the least.
But wait… that doesn’t make sense. Why would I need to send an email to my clients, every minute?
Well, I said a cron checks every minute, after all, didn’t I?
True, that is correct, it would (probably!) not make sense, but I also didn’t say that we have to do something every minute. I just said that the cron will check every minute if it has something to do.
We can schedule it to do something whenever we want, every minute, every hour, every end of the month, once a year, etc, by creating a cron job.
What is a cron job?
So what is a cron job, in simple words? In simple terms, a cron job is a task, that is automated and set to repeat. This task is saved in a file called crontab and it will execute automatically based on your set schedule.
Setting time for the cron job
The formatting used, when adding a cron job, to state when we want our task to be executed is:
<when> <what>
when: when we want something to happen.
what: what we want our cron to do at that point in time.
Let’s see the cron job formatting in more detail before we discover where to write a cron job. For our cron to understand when something should happen we need to add the following information:
minute | hour | day of month | month | day of week |
What? What is this? 😩 All good, we’ll figure it out.
We need to find a way to describe in great detail and without any doubts when a job (a cron’s task) should be executed. By combining these columns we can define any point in time we want our job to run. Let’s figure out more, through the following examples. 🧐
If we wanted to ask a cron to do something every minute, we should write it like this:
Every minute
minute | hour | day of month | month | day of week |
* | * | * | * | * |
Using *
is the same as saying, every minute of every hour of every day of the month…
Daily at 10:00
minute | hour | day of month | month | day of week |
0 | 10 | * | * | * |
See that we set the hour column to 10
and minute to 0
? This means that our task will run only in the first minute of the 10th hour. If we wanted our task to run every minute of the 10th hour we should set the minute column to *
.
Every Saturday at 10:00
minute | hour | day of month | month | day of week |
0 | 10 | * | * | 6 |
Saturday is the sixth day of the week so we define it by adding the number 6
on the “day of week“ column.
On the 1st day of every month at 15:30
minute | hour | day of month | month | day of week |
30 | 15 | 1 | * | * |
For the first 7 days of each month at 00:00
minute | hour | day of month | month | day of week |
0 | 0 | 1-7 | * | 6 |
We can also use duration, in this case, 1-7
is used for all days starting from the 1st till the 7th.
Every 30 minutes on working hours
minute | hour | day of month | month | day of week |
*/30 | 10-18 | * | * | * |
There is an awesome site called crontab.guru if you’d like to play around and see more complex cases of cron time settings. I suggest you check it out and bookmark it, it will come in handy, trust me!
Exploring the crontab file
Now that we are a bit more familiar with the way we set the time for our cron job, let’s see the where part.
There’s a file in our system called crontab. The word crontab comes from the combination of the words cron + table. This is the file in which we will be adding our instructions on what we want our cron to do and when we would like that to happen.
You can find the crontab file living inside the /var/spool/cron/crontabs
folder. In thecrontabs
folder you will find one crontab file per system user, in my case my crontab file name was george
. Do not edit this file directly though, if you want to edit your assigned file, type in your terminal:
crontab -e
Bashℹ️ -e stands for edit.
If it is the first time you open crontab you might be asked to select your preferred editor, I prefer vim, you can select whatever you like.
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
BashIn my case pressing 2
and hitting Enter
my crontab opened.
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
~
~
Under the last line of this file, (# m h dom mon dow command) let’s write our first actual cron! 🥳🥳🥳
How to write your first cron
Our first cron will be running every minute so that we can start our victory dance as soon as possible 🤭
# m h dom mon dow command
# my first cron instructions
* * * * * echo "This is my FIRST CRON!!! :)" > /dev/pts/1
Let’s break down a bit this command
# m h dom mon dow command
# my first cron instructions
* * * * * echo "This is my FIRST CRON!!! :)" > /dev/pts/1
Starting a line with a #
indicates that this is a comment. Adding comments could help if you have, for example, more than one crons and it gets difficult to understand what each of them does.
Watch out not to add comments in line with your cron command since they will be considered as a part of the command.
White spaces and blank lines are ignored in this file so feel free to format it however you’d like.
# m h dom mon dow command
# my first cron instructions
* * * * * echo "This is my FIRST CRON!!! :)" > /dev/pts/1
* * * * *
These are the 5 values of the columns we described in our previous section. Don’t forget to add spaces between each *
.
echo "This is my FIRST CRON!!! :)"
displays the message “This is my FIRST CRON!!! :)”.
ℹ️ echo
is a Linux command used to print strings/texts on the terminal.
>
is a symbol used to take a command’s output and redirect it somewhere else. So in this case the result of the echo
command – what the echo command
would print in the cron’s terminal – will be redirected to the next argument 👇
/dev/pts/1
#%$#@? 😟 Oh sorry I think I accidentally wrote my actual thought when I searched about it 🤓. I was trying to create a cron that just prints/displays a message in the terminal.
The problem is that crons have their own console so I needed to explicitly ask our cron to display a message in the terminal I am using.
To find which terminal I was using I typed in my terminal, tty
and got the following response
~ tty
/dev/pts/1
BashSo I added this terminal’s description in my cron command.
To wrap this up we’d say that we asked our first cron to display the message This is my FIRST CRON!!! :)
to our currently open terminal.
By saving and closing the crontab
file you should see a message crontab: installing new crontab
which informs you that all changes added to your crontab file were saved.
At the beginning of the next minute, you should see in your terminal your first cron running.
Wait for it…. wait waaaaaaaaait waiiiit (brings back memories from Braveheart!) now! Did you see it????? 🥳🥳🥳🥳
This is my FIRST CRON!!! :)
BashThis message will show up every minute forever so you probably need to edit your crontab and remove this cron, after all, it was just for learning purposes! 🤭
(Just type crontab -e
and remove the cron job you have added to do so.)
Where to find my cron logs?
If you haven’t modified your system settings, then by default, all system logs are kept in the /var/logs/systemlog
file. Typing the following command in your terminal will get you all CRON-related logs written in your system
grep CRON /var/log/syslog
Bashℹ️ grep
command searches for patterns inside a file
In my case, the result of it looked like
Jan 24 20:18:01 george CRON[224509]: (george) CMD (echo "This is my FIRST CRON!!! :)" > /dev/pts/5)
Jan 24 20:19:01 george CRON[224892]: (george) CMD (echo "This is my FIRST CRON!!! :)" > /dev/pts/5)
Jan 24 20:20:01 george CRON[225143]: (george) CMD (echo "This is my FIRST CRON!!! :)" > /dev/pts/5)
Jan 24 20:21:01 george CRON[225356]: (george) CMD (echo "This is my FIRST CRON!!! :)" > /dev/pts/5)
BashThis is, I guess, one way you can use to check what’s going on with your crons and when they ran.
And there you have it! You created your first cron and saw all the little details about your new cron job! Well done! It’s time for more victory dance!