Cron Jobs in Linux Crontab — Step-by-Step Tutorial
Every Linux distribution ships with cron, the daemon that runs scheduled commands in the background. This tutorial walks through creating, listing, and removing crontab entries, plus the environment quirks that catch almost every developer the first time they move a script from their terminal into cron.
Step 1: Open your crontab with crontab -e
Each user on the system has their own crontab. To edit yours:
$ crontab -e # first time you run this, it may ask which editor to use: # 1. /bin/nano <---- easiest for beginners # 2. /usr/bin/vim.basic # choose 1 and press Enter
This opens an empty (or existing) crontab file. Every non-comment line is one scheduled job in the format minute hour day month weekday command.
Step 2: Add your first job
# Run a backup script every day at 2:30 AM 30 2 * * * /home/deploy/scripts/backup.sh # Save and exit: # nano: Ctrl+O, Enter, then Ctrl+X # vim: Esc, then :wq, Enter
After saving, cron reloads the crontab automatically — no need to restart any service. Verify it was saved with crontab -l (list) at any time.
Step 3: Redirect output so you can actually see what happened
By default, cron tries to email job output to you, but most servers don't have local mail configured, so output silently disappears. Always redirect explicitly:
# Append both stdout and stderr to a log file 30 2 * * * /home/deploy/scripts/backup.sh >> /home/deploy/logs/backup.log 2>&1 # Discard output entirely (not recommended — you lose error visibility) 30 2 * * * /home/deploy/scripts/backup.sh > /dev/null 2>&1
Step 4: Fix the #1 gotcha — PATH and environment variables
Cron does not load your .bashrc, .bash_profile, or .profile. It runs with a bare-minimum environment, so a script that calls node, python3, or npm by name — and works fine in your terminal — often fails silently or with "command not found" under cron.
- Use full absolute paths in crontab commands:
/usr/bin/nodeinstead ofnode. - Or set
PATHexplicitly at the top of the crontab file:PATH=/usr/local/bin:/usr/bin:/bin. - Or source your environment at the top of the script itself, e.g.
source /home/deploy/.nvm/nvm.shbefore callingnode. - Check exactly what environment cron gives you by scheduling
* * * * * env > /tmp/cron-env.txtonce, then deleting the entry.
# Top of crontab — set PATH and any env vars all jobs need PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/bin NODE_ENV=production */10 * * * * /usr/bin/node /home/deploy/app/sync.js
Step 5: Other crontab commands you'll need
crontab -l— list the current user's crontab entries.crontab -r— remove the entire crontab for the current user (no confirmation — be careful).sudo crontab -u username -e— edit another user's crontab (requires root)./etc/crontaband/etc/cron.d/— system-wide crontabs; these require an extra "user" field between the schedule and the command.systemctl status cron(Debian/Ubuntu) orsystemctl status crond(RHEL/CentOS) — confirm the cron daemon itself is running.
Frequently Asked Questions
Run crontab -e in a terminal. This opens your user crontab in the default editor (often vi or nano). Add one cron expression per line, save, and exit — cron picks up the changes automatically without needing a restart.
The most common cause is PATH. Cron runs with a minimal environment, usually just /usr/bin:/bin, so commands that work in your interactive shell (which loads .bashrc or .profile) may not be found. Always use absolute paths to binaries and scripts in crontab entries.
By default cron emails any stdout or stderr output to the crontab owner using the local mail system, if one is configured. In practice most servers don't have mail set up, so output is silently lost unless you explicitly redirect it to a log file.