-
Notifications
You must be signed in to change notification settings - Fork 0
Classic Crontabs
yacron2's native configuration is YAML, but it also reads classic
(Vixie-style) crontabs, the m h dom mon dow command format described by
man 5 crontab. You can point -c at an existing crontab, drop one into a
config directory next to your YAML files, or pull one in with include:, and
every entry runs as a first-class yacron2 job.
The contract is deliberately one-directional: the crontab syntax is
supported, but the configuration around it is not emulated. Each entry is
lowered into an ordinary job definition and then built exactly like a YAML
job, so it carries yacron2's standard defaults (UTC schedules, stderr and
exit-status failure detection, concurrencyPolicy: Allow, no retries, and so
on), not a re-creation of cron's environment, mailer, or quirks. The
deviations section below lists every place that
matters and what to do about each. All behavior on this page is implemented
in yacron2/crontabs.py and yacron2/config.py.
The file name decides whenever it can:
| Name | Treated as |
|---|---|
*.crontab, *.cron (case-insensitive) |
classic crontab |
a file named exactly crontab (case-insensitive), e.g. a crontab -l > crontab export |
classic crontab |
*.yml, *.yaml
|
YAML, always; never content-sniffed |
anything else, passed explicitly with -c or pulled in with include:
|
content-sniffed (below) |
| anything else, inside a config directory | skipped, as before |
Name recognition also fires on /etc/crontab, but note that system
crontabs (/etc/crontab, /etc/cron.d) carry a sixth user column that
yacron2 does not parse; only the five-field user-crontab format runs as-is
(see deviations).
In a config directory, crontab-named files load right alongside
*.yml/*.yaml files, in the same name-sorted order, and the usual skip
rule still applies: entries whose name starts with _ or . are ignored
(see Includes, Defaults, and Multi-File Config).
The content sniff exists so that yacron2 -c /var/spool/cron/crontabs/root
just works even though the file has no telling name. It looks at the first
meaningful (non-blank, non-comment) line only, and only accepts shapes no
valid yacron2 YAML document can open with: a NAME=value assignment, a line
starting with @, or five valid cron fields followed by a command. Anything
inconclusive is parsed as YAML, so extensionless YAML configs keep their
exact pre-existing behavior. When in doubt, name the file *.crontab and
the question never arises.
A YAML config can also pull a crontab in directly:
include:
- legacy.crontabyacron2 -v -c legacy.crontab validates a crontab the same way it validates
YAML; parse errors are reported with the offending file:line. A runnable
example mixing a crontab with a YAML file (and the web dashboard) ships in
the repository as example/crontab.
The user-crontab format from man 5 crontab:
# comments and blank lines are ignored
SHELL=/bin/bash
PATH = /usr/local/bin:/usr/bin:/bin
MAILTO="ops@example.com"
# m h dom mon dow command
*/15 * * * * /usr/local/bin/backup --incremental
30 4 * * mon-fri /usr/local/bin/report --daily
0 0 1 jan * /usr/local/bin/happy-new-year
CRON_TZ=Europe/Berlin
0 6 * * * echo "6am in Berlin, not UTC"
@daily /usr/local/bin/rotate-logs
@reboot echo "yacron2 started"
0 0 * * * pg_dump mydb > /backup/mydb-$(date +\%F).sqlSpecifically:
-
Entries: five time fields, then the rest of the line is the command.
Ranges (
1-5), steps (*/5), lists (1,15,30), and month/weekday names (jan,mon-fri) are supported; day-of-week accepts both0and7as Sunday. The field dialect is the same parse-crontab library that parses YAMLschedulestrings, so both formats accept identical expressions (see Schedules and Timezones). -
Nicknames:
@reboot,@yearly,@annually,@monthly,@weekly,@daily,@midnight,@hourly.@midnightis rewritten to its synonym@dailyat load time;@rebootbehaves exactly like a YAML@rebootschedule (runs once at startup, and understands leadership under clustering). -
Environment assignments:
NAME = valuelines apply to the entries below them, exactly as in cron; a later reassignment affects later entries only. Values may be single- or double-quoted to preserve leading or trailing blanks. All assignments are exported to the job's environment, on top of the environment yacron2 itself runs with. -
Escaped percent signs:
\%in a command becomes a literal%, so the ubiquitousdate +\%Fidiom works unchanged. An unescaped%is a load-time error; see deviations.
Two assignments are interpreted as well as exported:
| Variable | Effect |
|---|---|
SHELL |
Sets the job's shell option, so the command runs as $SHELL -c "command", as in cron. Without it, yacron2's standard default applies (/bin/sh on POSIX, the native command processor on Windows). |
CRON_TZ |
Sets the job's timezone option: schedules below it are evaluated in that IANA zone (cronie's CRON_TZ semantics). An unknown zone is a load-time error at the assignment's line. |
Every entry is lowered to a plain job definition, merged over the same
built-in defaults as a YAML job (DEFAULT_CONFIG), and validated by the
same JobConfig code path. From that point on, nothing downstream can tell
the two formats apart: crontab jobs appear in the
web dashboard and HTTP API, participate in the
job-set fingerprint and
clustering, and report failures like any
other job.
The defaults that matter most for a migrated crontab. Each row names a behavior (with the per-job YAML option behind it), what the entry does now that yacron2 runs it, and what the same line did under classic cron:
| Behavior | Under yacron2 | Under classic cron |
|---|---|---|
time basis (utc / timezone) |
UTC (set CRON_TZ to change) |
local time |
failure detection (failsWhen) |
non-zero exit or any stderr output is a failure | exit status ignored; output mailed |
output (captureStderr / captureStdout) |
stderr is read by yacron2 (for failure detection, reports, and the dashboard log tail) and re-emitted into its log with a [<job> stderr] prefix; stdout is not read: it flows straight through to yacron2's own stdout, visible there but not to reports or the dashboard |
both mailed to MAILTO
|
concurrency (concurrencyPolicy) |
Allow (overlapping runs permitted) |
overlapping runs permitted |
retries (onFailure.retry) |
none | none |
user (user) |
the user yacron2 runs as | the crontab's owner |
There is no way to override these from inside a crontab (the format has no
vocabulary for it); that is by design. A crontab gets you running with
sensible, predictable standards, and the moment an entry needs reporting,
retries, timeouts, or any other per-job option, move that entry to YAML,
where every option in the Configuration Reference
is available. Note that a defaults: section in a sibling or including YAML
file does not apply to crontab entries, for the same reason per-file
defaults never cross files (see
Includes, Defaults, and Multi-File Config).
Entries are named <file name>:<line number>, for example
legacy.crontab:9. The name is unique within a file, stable across reloads
while the file is unchanged, shows up in logs, the dashboard, and the HTTP
API like any other job name, and points you straight at the source line.
Inserting or removing lines renumbers the entries below the edit, which
yacron2 treats the same way as renaming a YAML job (the old name's run
history ends and the new name starts fresh).
Each of these is a deliberate choice in favor of yacron2's standard behavior, made loudly rather than silently:
-
Schedules default to UTC, not local time. This is yacron2's standard
and by far the least surprising choice in containers. Put
CRON_TZ=<zone>above the entries that need a specific zone. -
MAILTOdoes not send mail. It is exported to the job's environment but not interpreted; a crontab has nowhere to declare an SMTP server, and yacron2's failure handling is richer than mail-on-output. Configure Reporting in YAML if you want failure mail. Failures are always visible in logs, the dashboard, and the HTTP API regardless: yacron2 reads each entry's stderr for exactly that purpose, while stdout is left unread and flows straight to yacron2's own stdout (see the table above). -
An unescaped
%is a load-time error, not stdin. In cron,%ends the command and everything after it is fed to the command as standard input. yacron2 does not feed stdin to jobs, and the silent alternatives are both worse: running the command without input it expects, or leaving the input text on the command line for the shell to execute. The escaped form\%(the common case, e.g.date +\%F) works exactly as in cron. For genuine stdin data, use a YAML job with a heredoc or file redirect. -
The system-crontab user column is not parsed.
/etc/crontaband/etc/cron.dfiles carry a sixth field naming the user to run as. A parser cannot reliably tell that column from the first word of a command, so yacron2 reads the five-field user-crontab format only; a user column would land at the start of the command (and typically fail withroot: command not foundat run time). Remove the column, or move the entry to YAML and use theuser:option (Commands and Environment). -
Cron's implicit environment is not injected. cron gives jobs a
near-empty environment with
LOGNAME,HOME, andSHELL=/bin/shdefaults. yacron2 jobs inherit yacron2's own environment plus the crontab's assignments, the same rule as YAML jobs. A crontab that relied on cron's minimalPATHbehaves the same once it setsPATH=itself, as most already do.
When an entry outgrows the crontab format, its YAML equivalent is mechanical. This entry:
CRON_TZ=Europe/Berlin
SHELL=/bin/bash
30 4 * * mon-fri /usr/local/bin/report --dailyis exactly:
jobs:
- name: report
command: /usr/local/bin/report --daily
shell: /bin/bash
schedule: "30 4 * * mon-fri"
timezone: Europe/Berlinplus whatever per-job options prompted the move. Both forms can coexist in one config directory for as long as the migration takes.
This wiki documents yacron2. See the README and the changelog.
yacron2 is a fork of gjcarneiro/yacron.
- Getting Started
- Configuration
- Job Behavior
- Integrations
- Reference and Development