cron and systemd timers: run something every night
Schedule a script with crontab or a systemd timer: the five cron fields, environment and PATH pitfalls, logging, catching up missed runs with Persistent=true, and how to check that it actually ran.
Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?
You have a script that works when you run it by hand and you want it to run at 02:30 every night. Linux gives you two standard tools: cron, which is simple and everywhere, and systemd timers, which give you logging, dependencies and catch-up of missed runs for free. This guide sets up the same nightly job both ways.
Before you start
- The script runs with no terminal and a nearly empty environment. Use absolute paths inside it and start it with
set -euo pipefail. - Make it executable:
chmod +x /usr/local/bin/nightly-report.sh. - Test it once from a clean shell:
env -i HOME="$HOME" PATH=/usr/bin:/bin /usr/local/bin/nightly-report.sh. If that fails, cron will fail the same way.
Option 1: cron
Each user has a crontab. Edit yours with crontab -e (it opens in your editor) and list it with crontab -l. A line has five time fields followed by the command.
# min hour day-of-month month day-of-week command
30 2 * * * /usr/local/bin/nightly-report.sh >> /var/log/nightly-report.log 2>&1
*means every value.*/15in the minute field means every 15 minutes.1-5in day-of-week means Monday to Friday.0,30lists values.- Shortcuts:
@daily(midnight),@hourly,@weekly,@reboot. - Set
[email protected]at the top to get any output by mail, or redirect output to a log file as above. A job that prints nothing and exits 0 is silent. - Set
PATH=/usr/local/bin:/usr/bin:/binat the top of the crontab; the default PATH in cron is minimal, which is whycommand not foundis the most common cron failure. - The
%character is special in crontab lines (it becomes a newline). Escape it as\%, for example indate +\%F.
System-wide jobs that must run as root go in /etc/cron.d/ as separate files with an extra user field before the command, or you simply drop an executable script into /etc/cron.daily/.
# /etc/cron.d/nightly-report
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=root
30 2 * * * root /usr/local/bin/nightly-report.sh >> /var/log/nightly-report.log 2>&1
Check that it ran: look at your log file, or at the cron daemon’s log with journalctl -u cron (Debian, Ubuntu) or journalctl -u crond (RHEL, Fedora), or grep CRON /var/log/syslog on older systems.
Option 2: a systemd timer
A timer is two small files: a .service that says what to run and a .timer that says when. Put them in /etc/systemd/system/.
# /etc/systemd/system/nightly-report.service
[Unit]
Description=Nightly report
[Service]
Type=oneshot
ExecStart=/usr/local/bin/nightly-report.sh
User=report
Nice=10
# /etc/systemd/system/nightly-report.timer
[Unit]
Description=Run nightly report at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=5m
[Install]
WantedBy=timers.target
Check before you run this
- Runs with administrator rights. Make sure you understand every line.
sudo systemctl daemon-reload
sudo systemctl enable --now nightly-report.timer
systemctl list-timers --all # next and last run of every timer
sudo systemctl start nightly-report.service # run the job right now, by hand
journalctl -u nightly-report.service -n 50 # its output, no redirection needed
Persistent=trueruns the job at boot if the machine was off when it was due. cron simply skips missed runs.RandomizedDelaySecspreads jobs on many machines so they do not all hit a server at the same second.- Check a calendar expression before you rely on it:
systemd-analyze calendar "Mon..Fri 02:30"prints the next run time. - Shortcuts such as
OnCalendar=daily,weeklyandhourlywork too.
Per-user timers without root go in ~/.config/systemd/user/ and are managed with systemctl --user. They only run while you are logged in unless you enable lingering with loginctl enable-linger $USER.
Which one to pick
- cron: a one-liner on a machine you do not own or that is not running systemd, or a quick personal job.
- systemd timer: anything on a server you maintain. You get
journalctllogs, catch-up of missed runs, resource limits andsystemctl statusfor free.
Whichever you choose, make the script itself safe to be started twice and loud when it fails. The cron-safe wrapper script in this encyclopedia adds locking, logging and failure reporting around any command.
Official documentation
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0164 systemd services: systemctl and journalctl basics systemd starts and supervises services on most Linux servers. systemctl starts, stops and enables them; journalctl shows their logs. Beginner · Explains an idea · Linux Article Services & systemd 15 Oct 2026
- 0165 Write a systemd service unit for your own app Turn any long-running program into a proper service: create a unit file, run it as an unprivileged user, restart it on failure… Intermediate · Step by step · Linux Article Services & systemd 15 Oct 2026
- 0166 Replace a cron job with a systemd timer A systemd timer runs a service on a schedule like cron, but logs every run to the journal, can catch up missed… Intermediate · Step by step · Linux Article Services & systemd 15 Oct 2026
- 0167 Fix: Job for nginx.service failed because the control process exited with error code systemctl prints this when a service's start command exits with an error. The real reason is in journalctl; for nginx it is… Intermediate · Fixes an error · Linux Article Networking & firewalls · Services & systemd 15 Oct 2026
- 0168 Server health check script: disk, memory and failed units A dependency-free bash script that checks disk and inode usage, available memory, load, failed systemd units and pending reboots, and exits non-zero… Intermediate · Cheat sheet · Linux Script Disks, LVM & filesystems · Services & systemd 15 Oct 2026
- 0255 Build a monitoring stack with Prometheus, node_exporter and Grafana on one Linux server Install Prometheus and node_exporter as systemd services, scrape and query host metrics with PromQL, then add Grafana with a dashboard and an… Intermediate · Guided project · Linux Article Prometheus & Grafana · Services & systemd 15 Oct 2026
Repos in the wild
- systemd: the Linux system and service manager systemd/systemd The source of systemd, the init system and service manager on most Linux distributions, together with journald, networkd, resolved, timers and the systemctl tool. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Dominik +4,293 chars