Cron jobs are useful for scheduling commands to run periodically. For example:
- Every 15 minutes
- Once per month
In this guide I will show you several common cron tasks and tips that I use including:
- Common scheduling examples
- Chaining together multiple programs
- Redirecting output
- Checking logs
- Running a script from a Python virtual environment
Cron is good for programs that run and then complete, like generating a report, but cron is not for services that stay running forever like a web server. If you want to have a program that continuously runs and you want to ensure the program stays running even if it crashes or the server restarts, you want to setup a service. Check out my tutorial on how to do that: Creating Systemd Service Files.
Cron is available in Linux and Mac operating systems, but not Windows.
How to edit cron jobs
You can use
crontab -e to edit cron jobs.
Note that each user has their own crontab.
This means if you run it without
sudo, you are editing
your users crontab and with
sudo you are editing Root's crontab.
You can use
-u <username> to specify which users crontab to edit.
This is useful if you want to edit a system user's crontab.
Read more about How to Create a Secure Linux System User
# Edit current user's crontab crontab -e # Edit root crontab sudo crontab -e # Edit a specific user's crontab sudo crontab -u some_user -e
You can list current cron jobs with:
sudo crontab -u some_user -l
Cron schedules edited with
crontab -e are stored in
/var/spool/cron but you should never
modify them directly.
You can also add cron jobs in the
/etc/cron.* directories, but personally, I prefer the
crontab -e method.
- Always use full path to files and executables
- Make sure your script is executable (
- If you need to perform several steps, put it in a shell script and call that script
- Use quotation marks for anything with spaces
- Do not run jobs as root unless absolutely necessary. Use the lowest privilege user possible.
A crontab entry has a specific format where the first five columns
represent the schedule and the rest of the line is considered the command.
You can use spaces or tabs to format a line.
Comment lines start with
# Month, Hour, Day of Month, Month, Day of Week, Command # M H DoM M DoW Command # Example: * * * * * /some/command --with-args
Here are some common examples that I have used myself. You can find a ton of useful examples for scheduling at crontab.guru.
Run every minute
* symbol means to run on every occurrence.
So in this case
* * * * * means:
- on every minute
- of every hour
- on each day of the month
- for each month
- and every day of the week
# Run every minute * * * * * /script/to/run
Run every 15 minutes
*/15 * * * * /thing/to/execute
Run nightly at 1:30 AM
30 1 * * * /path/to/command
Run weekly on Sunday at 4:30 AM
For the Day of Week field (the 5th column) Sunday = 0 and Saturday = 6.
30 4 * * 0 /path/to/script
Run monthly on the 1st at 2:15 AM
First of the month is Day of Month of
1 (column 3).
15 2 1 * * /path/to/executable
Run a command from a Python virtual environment
To use a Python virtual environment to run Python, pip, or a script that was installed by a package.
There is no need to "activate" the virtual environment or create a separate script to activate and then run. You can simply invoke the Python interpreter directly from the virtual environment using its full path. It will automatically use the packages associated with that virtual environment location.
To learn more, check out my Python Virtual Environments Tutorial.
* * * * * /path/to/venv/bin/python /path/to/script.py
Pass environment variables
You can set environment variables directly in a command like this example.
* * * * * MY_ENV_VAR=123 ANOTHER_VAR="hi" /path/to/script.sh
Stringing together multiple commands
This example will run multiple commands in a row.
If any script fails (returns a non-zero exit code), it will exit and not run the next command.
&& will only continue is the previous script executed successfully and returned
* * * * * /script1 && /script2 && /script3
You may want to override the default output settings for a cron job to ensure you capture output to a file or to discard output so it does not write to disk. I will demonstrate some examples of each.
To learn more about redirecting output in general, check out my tutorial, STDIN, STDOUT, STDERR, Piping, and Redirecting.
Redirect stderr to stdout
If you cron is only logging standard output, but not standard error, you can redirect stderr to stdout.
# Redirect stderr to stdout * * * * * /script 2>&1
Redirect output to a log file
Depending on the logging situation of your server, output from cron execution may not be logged at all. In those cases you may want to redirect output to a file. You can also redirect standard error to standard output to ensure everything is captured.
# Redirect output to a specific file * * * * * /script > /my/log.txt 2>&1
On the other hand, you may have thorough logging of the cron execution output, but
you may want to discard all of it instead of filling up disk space. In these
situations you can redirect to
# Redirect output to /dev/null if you do not want the output to go anywhere * * * * * /script > /dev/null 2>&1
View cron logs
It may differ by Linux distribution, but there are a couple places to look:
journalctloutput from systemd's
- Log files in
# View systemd logging journalctl -u cron # Tail systemd log for cron journalctl -u cron -f
To view the log file in
# View cron log file less /var/log/cron # Tail cron log file tail -f /var/log/cron
After reading this, you should understand how to setup basic cron jobs for