A modern Cron replacement that is Docker-friendly
- Free software: MIT license
- "Crontab" is in YAML format;
- Builtin sending of Sentry and Mail outputs when cron jobs fail;
- Flexible configuration: you decide how to determine if a cron job fails or not;
- Designed for running in Docker, Kubernetes, or 12 factor environments:
- Runs in the foreground;
- Logs everything to stdout/stderr [1];
- Option to automatically retry failing cron jobs, with exponential backoff.
[1] | Whereas vixie cron only logs to syslog, requiring a syslog daemon to be running in the background or else you don't get logs! |
Configuration is in YAML format. To start yacron, give it a configuration file
or directory path as the -c
argument. For example:
yacron -c /tmp/my-crontab.yaml
This starts yacron (always in the foreground!), reading /tmp/my-crontab.yaml
as configuration file.
This configuration runs a command every 5 minutes:
jobs:
- name: test-01
command: echo "foobar"
shell: /bin/bash
schedule: "*/5 * * * *"
The command can be a string or a list of strings. If command is a string,
yacron runs it through a shell, which is /bin/bash
in the above example, but
is /bin/sh
by default.
If the command is a list of strings, the command is executed directly, without a shell. The ARGV of the command to execute is extracted directly from the configuration:
jobs:
- name: test-01
command:
- echo
- foobar
schedule: "*/5 * * * *"
The schedule option can be a string in the traditional crontab format, or can be an object with properties. The following configuration runs a command every 5 minutes, but only on the specific date 2017-07-19, and doesn't run it in any other date:
jobs:
- name: test-01
command: echo "foobar"
schedule:
minute: "*/5"
dayOfMonth: 19
month: 7
year: 2017
dayOfWeek: "*"
You can ask for environment variables to be defined for command execution:
jobs:
- name: test-01
command: echo "foobar"
shell: /bin/bash
schedule: "*/5 * * * *"
environment:
- key: PATH
value: /bin:/usr/bin
There can be a special defaults
section in the config. Any attributes
defined in this section provide default values for cron jobs to inherit.
Although cron jobs can still override the defaults, as needed:
defaults:
environment:
- key: PATH
value: /bin:/usr/bin
shell: /bin/bash
jobs:
- name: test-01
command: echo "foobar" # runs with /bin/bash as shell
schedule: "*/5 * * * *"
- name: test-02 # runs with /bin/sh as shell
command: echo "zbr"
shell: /bin/sh
schedule: "*/5 * * * *"
Yacron has builtin support for reporting jobs failure (more on that below) by email and Sentry (additional reporting methods might be added in the future):
- name: test-01
command: |
echo "hello" 1>&2
sleep 1
exit 10
schedule:
minute: "*/2"
captureStderr: true
onFailure:
report:
sentry:
dsn:
value: example
# Alternatively:
# fromFile: /etc/secrets/my-secret-dsn
# fromEnvVar: SENTRY_DSN
mail:
from: [email protected]
to: [email protected]
smtp_host: 127.0.0.1
Here, the onFailure
object indicates that what to do when a job failure
is detected. In this case we ask for it to be reported both to sentry and by
sending an email.
The captureStderr: true
part instructs yacron to capture output from the the
program's standard error, so that it can be included in the report. We could
also turn on standard output capturing via the captureStdout: true
option.
By default, yacron captures only standard error. If a cron job's standard error
or standard output capturing is not enabled, these streams will simply write to
the same standard output and standard error as yacron itself.
It is possible also to report job success, as well as failure, via the
onSuccess
option.
- name: test-01
command: echo "hello world"
schedule:
minute: "*/2"
captureStdout: true
onSuccess:
report:
mail:
from: [email protected]
to: [email protected]
smtp_host: 127.0.0.1
By default, yacron considers that a job has failed if either the process returns a non-zero code or if it generates output to standard error (and standard error capturing is enabled, of course).
You can instruct yacron how to determine if a job has failed or not via the
failsWhen
option:
failsWhen:
producesStdout: false
producesStderr: true
nonzeroReturn: true
- producesStdout
- If true, any captured standard output causes yacron to consider the job as failed. This is false by default.
- producesStderr
- If true, any captured standard error causes yacron to consider the job as failed. This is true by default.
- nonzeroReturn
- If true, if the job process returns a code other than zero causes yacron to consider the job as failed. This is true by default.
It is possible to instruct yacron to retry failing cron jobs by adding a
retry
option inside onFailure
:
- name: test-01
command: |
echo "hello" 1>&2
sleep 1
exit 10
schedule:
minute: "*/10"
captureStderr: true
onFailure:
report:
mail:
from: [email protected]
to: [email protected]
smtp_host: 127.0.0.1
retry:
maximumRetries: 10
initialDelay: 1
maximumDelay: 30
backoffMultiplier: 2
The above settings tell yacron to retry the job up to 10 times, with the delay between retries defined by an exponential backoff process: initially 1 second, doubling for every retry up to a maximum of 30 seconds.
If the cron job is expected to fail sometimes, you may wish to report only in
the case the cron job ultimately fails after all retries and we give up on it.
For that situation, you can use the onPermanentFailure
option:
- name: test-01
command: |
echo "hello" 1>&2
sleep 1
exit 10
schedule:
minute: "*/10"
captureStderr: true
onFailure:
retry:
maximumRetries: 10
initialDelay: 1
maximumDelay: 30
backoffMultiplier: 2
onPermanentFailure:
report:
mail:
from: [email protected]
to: [email protected]
smtp_host: 127.0.0.1