
Linux has always been a bit scary and hard to approach for non-techies. Users spend a lot of time on the command line, typing commands that only other Linux users understand. In fact, they’d spend even more time linuxing if it wasn’t for cron, a utility program responsible for job scheduling. Cron automates the regular and periodical system maintenance by running cron jobs which Windows developers know as scheduled tasks. The timetable where the jobs are scheduled is called crontab, short for cron table, as is the tool that installs the cron job schedule. Let’s take a closer look…
What happens at regular intervals on your Linux machine?
Linux tries to do as much housekeeping and self-care as possible to be easier to use. If a user session expires before the user ends it, the session data becomes garbage which Linux cleans every hour. Log files are a useful source of information that answer questions like “What just happened?” but, in time, they too become garbage. The usual daily practice is log rotation that renames “log_of_today” to “log_of_yesterday”, creates a new empty “log_of_today” file, and removes the “log_of_30_days_ago” file. If we run a web server on Linux, we probably have a cron job that checks the validity of the installed SSL certificates twice a day and renews them before they expire. Applications like Google Chrome set up their own cron jobs that check for updates and fix the configuration in the case where a system upgrade breaks it.
Basically, anything that we can run on the command line, can be configured to run by cron at regular time intervals. The usual tasks are about system administration and maintenance but we can also use cron jobs to run operational tasks for our own web application. For example, we can configure when automatic email messages are sent and when we synchronize our data with external data sources.
Setting up your own cron jobs with crontab
These are the useful commands to view and edit your own cron jobs and the system-wide root user’s cron jobs:

The structure of the crontab is simple: there is one line per one cron job and that line starts with a cron expression and is followed by the command. The first five fields of the cron expression are 1. minute (0-59), 2. hour (0-23), 3. day of the month (1-31), 4. month (1-12), 5. day of the week (0-6). For example, we define cron jobs where the user writes words into the null device:

Every year, on 3 April at 02:01, the word is ‘foo’, every 5 minutes ‘bar’, and at 5 past every hour ‘baz’. Note that each line must end in a newline character. Crontabs may also include comments so that anything after the hash character # until the end of the line is ignored by cron. Saving changes in the editor will save the crontab but only exiting the editor will install the new cron jobs.
Looking under the hood
Those who are curious about the Linux internals want to know where to find all the crontabs. The user crontabs are kept in /var/spool/cron/crontabs While the files can be edited there, they won’t be installed or reloaded by the editor, so it’s better to not touch them manually.
The system-wide crontabs are stored in /etc/cron.d/ Notice that these crontabs have a slightly different syntax in that we specify a username between the cron expression and the command. The username denotes who will run the command.

This example comes with a PHP installation. It configures a cron job where the root user runs the command every 9 and 39 minutes past the hour. The command, written without line breaks, calls a PHP session cleaner script if 1) the script is executable and 2) if the Linux system service manager is not running and taking care of the cleanup.
Cron jobs are also created without adding more crontab entries by placing the executable file in one of the following directories:
/etc/cron.hourly
/etc/cron.daily
/etc/cron.weekly
/etc/cron.monthly
Most files in these directories are shell scripts and Perl scripts that monitor package manager updates, create statistics, crash reports, and backup files. These cron jobs are scheduled by anacron which is an alternative to cron. Anacron doesn’t assume that the system is always up when cron jobs are scheduled, i.e. it’s designed to ensure that a daily cron job runs once a day even if the system is down during the scheduled start time.
Cron jobs making a mess
Things don’t always go as planned. Setting up the server side of a web application requires accuracy from the file and directory permissions that protect the code from outsiders but at the same time allow access to the appropriate processes. We let out a sigh of relief when everything is set, only to wake up the next day to see how nothing works! Then we ask the Linux administrator to fix the file permissions until they break again, and again, at regular intervals. Soon we understand that the culprit is a cron job, running as root, writing code files in the application cache that the web server is not permitted to read. Rather than having someone fix the permissions every day, we should configure the cron job to run as the web server instead.
One solution is to create the cron job in /etc/cron.d/ and make www-data the user, assuming that www-data is the owner of the web server worker processes. Another solution is to switch the user with su in the cronjob command:
0 0 * * * su www-data -s /bin/bash -c 'cd ~/myapp && ./myexec'
This example defines that every midnight, as the www-data user, we go to a ‘myapp’ directory and run a ‘myexec’ script. In general, we should double-check the owner of the cron job process for every cron job that creates or edits files.
Troubleshooting
When anything seems to be wrong with our cron job, we can actually be right there and monitor what happens because we know the exact time it should start. If the job seems to be stuck in a never-ending loop as we are watching, we can attach strace to the process and see what the job is doing, if anything. For the less experienced Linux users, though, there is an easier way. We take a look inside /var/log/syslog and filter it for entries that start with CRON:
grep CRON /var/log/syslog
The output shows the answer to the common question about all cron jobs: did it run or not? An entry in the log means that the scheduled job started on time.
These log entries show that the PHP session cleaning cron job started at 12:09 and 12:39. What happens during the execution needs to be logged by the job itself because cron only logs errors with the scheduling of the jobs.
Running daily, a day early?
Once we get the hang of it, cron is one of the easiest details to understand about Linux. It requires no programming skills or any theoretical background knowledge. We only need to know how to use a text editor and we’re ready to configure cron jobs. But wait, what about time, the scheduled launch time of the job? Yes, we do need to understand time. I too once thought that time couldn’t be hard to understand until I was asked to reconfigure a cron job that was running every day at noon. “Please make it run one day earlier!“
Read our latest posts:
- Agility Isn’t Dead. It’s Finally Becoming Real
- AI Is Reshaping Web Development — But Not in the Way People Think
- Will AI Replace Developers? A Reality Check From the Field
- Teaching AI and Software Development at Chulalongkorn University: A Two-Hour Conversation That Went Well Beyond the Slides
- Skipping Figma Doesn’t Mean Skipping Design