flashman
← All guides

Expand cron nicknames before you trust them

Expand crontab nicknames such as @daily and @hourly into five fields, then preview those fields in the daemon's timezone before you depend on them.

2026-10-14 · 7 min read

  • cron
  • scheduling
  • operations

A nickname in a Vixie crontab is a macro for a schedule, except @reboot, which is an event. The macros are easy to read and easy to mis-deploy, because the daemon that will run the job may not be Vixie cron.

The durable form is the five fields plus a sentence and a timezone. The nickname can stay in a comment. The scheduler should see the fields.

Map each nickname once

@hourly expands to 0 * * * *. @daily and @midnight expand to 0 0 * * *. @weekly expands to 0 0 * * 0, which is Sunday. @monthly expands to 0 0 1 * *. @yearly and @annually expand to 0 0 1 1 *. These are calendar times in the cron daemon's timezone, not intervals measured from the last run.

@reboot runs when crond starts. It is not hourly, and it is not a retry. A job that must run at boot and every night is two entries. A job that must survive an application crash is a process supervisor, not a cron nickname.

  • Write the five fields under the nickname.
  • Name the timezone beside the fields.
  • Keep @reboot on its own line.
  • Do not paste nicknames into a parser you have not tested.

Match the file format

A user crontab is five fields and a command. A system crontab such as /etc/crontab is five fields, a user, and a command. Copying a nickname line between those files shifts the command into the user column or the user into the command.

Kubernetes CronJob and systemd timers have their own grammars. Expand the nickname yourself and translate the fields. A previous guide covers systemd OnCalendar. This one stops at the crontab macro.

Preview midnight where the host thinks it is

Set the cron tool's timezone to the daemon's zone and paste the five fields. Compare the first preview with a log timestamp from the host. If they disagree by hours, the daemon is not in the zone you typed.

Sunday, the first of the month, and 1 January are the boundaries that distinguish @weekly, @monthly, and @yearly. Preview one of each before you call the migration done. A job that has only run on a Wednesday has not tested @weekly.

Leave a sentence in the repo

Above the line, write the human schedule: daily at 00:00 UTC, or when crond starts. The five fields are the executable form. The sentence is what a reviewer can disagree with. Diff both when the schedule changes.

Use Flashman's cron tool on the expanded fields, the timestamp converter when a log line has an offset, diff on the crontab, and the Markdown editor for the sentence. The nickname can remain as a comment if the daemon ignores comments.

Try these tools