mirror of
https://github.com/aptible/supercronic.git
synced 2025-09-26 20:31:17 +08:00
ADD README / LICENSE
This commit is contained in:
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017, Aptible, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
152
README.md
Normal file
152
README.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Supercronic #
|
||||||
|
|
||||||
|
Supercronic is a crontab-compatible job runner, designed specifically to run in
|
||||||
|
containers.
|
||||||
|
|
||||||
|
|
||||||
|
## Why Supercronic? ##
|
||||||
|
|
||||||
|
Crontabs are the lingua franca of job scheduling, but typical server cron
|
||||||
|
implementations are ill-suited for container environments:
|
||||||
|
|
||||||
|
- They purge their environment before starting jobs. This is an important
|
||||||
|
security feature in multi-user systems, but it breaks a fundamental
|
||||||
|
configuration mechanism for containers.
|
||||||
|
- They capture the output from the jobs they run, and often either want to
|
||||||
|
email this output or simply discard it. In a containerized environment,
|
||||||
|
logging task output and errors to `stdout` / `stderr` is often easier to work
|
||||||
|
with.
|
||||||
|
- They often don't respond gracefully to `SIGINT` / `SIGTERM`, and may leave
|
||||||
|
running jobs orphaned when signaled. Again, this makes sense in a server
|
||||||
|
environment where `init` will handle the orphan jobs and Cron isn't restarted
|
||||||
|
often anyway, but it's inappropriate in a container environment as it'll
|
||||||
|
result in jobs being forcefully terminated (i.e. `SIGKILL`'ed) when the
|
||||||
|
container exits.
|
||||||
|
- They often try to send their logs to syslog. This conveniently provides
|
||||||
|
centralized logging when a syslog server is running, but with containers,
|
||||||
|
simply logging to `stdout` or `stderr` is preferred.
|
||||||
|
|
||||||
|
Finally, they are often very quiet, which makes the above issues difficult to
|
||||||
|
understand or debug!
|
||||||
|
|
||||||
|
The list could go on, but the fundamental takeaway is this: unlike typical
|
||||||
|
server cron implementations, Supercronic tries very hard to do exactly what you
|
||||||
|
expect from running `cron` in a container:
|
||||||
|
|
||||||
|
- Your environment variables are available in jobs.
|
||||||
|
- Job output is logged to `stdout` / `stderr`.
|
||||||
|
- `SIGTERM` (or `SIGINT`, which you can deliver via CTRL+C when used
|
||||||
|
interactively) triggers a graceful shutdown
|
||||||
|
- Job return codes and schedules are also logged to `stdout` / `stderr`.
|
||||||
|
|
||||||
|
## How does it work? ##
|
||||||
|
|
||||||
|
- Install Supercronic (see below).
|
||||||
|
- Point it at a crontab: `supercronic CRONTAB`.
|
||||||
|
- You're done!
|
||||||
|
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
- If you have a `go` toolchain available: `go install github.com/aptible/supercronic`
|
||||||
|
- TODO: Docker installation instructions / packaging.
|
||||||
|
|
||||||
|
|
||||||
|
## Crontab format ##
|
||||||
|
|
||||||
|
Broadly speaking, Supercronic tries to process crontabs just like Vixie cron
|
||||||
|
does. In most cases, it should be compatible with your existing crontab.
|
||||||
|
|
||||||
|
There are, however, a few exceptions:
|
||||||
|
|
||||||
|
- First, Supercronic supports second-resolution schedules: under the hood,
|
||||||
|
Supercronic uses [the `cronexpr` package][cronexpr], so refer to its
|
||||||
|
documentation to know exactly what you can do.
|
||||||
|
- Second, Supercronic does not support changing users when running tasks.
|
||||||
|
Again, this is something that hardly makes sense in a cron environment. This
|
||||||
|
means that setting `USER` in your crontab won't have any effect.
|
||||||
|
|
||||||
|
Here's an example crontab:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Run every minute
|
||||||
|
*/1 * * * * echo "hello"
|
||||||
|
|
||||||
|
# Run every 2 seconds
|
||||||
|
*/2 * * * * * * ls 2>/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Environment variables ##
|
||||||
|
|
||||||
|
Just like regular cron, Supercronic lets you specify environment variables in
|
||||||
|
your crontab using a `KEY=VALUE` syntax.
|
||||||
|
|
||||||
|
However, this is only here for compatibility with existing crontabs, and using
|
||||||
|
this feature is generally **not recommended** when using Supercronic.
|
||||||
|
|
||||||
|
Indeed, Supercronic does not wipe your environment before running jobs, so if
|
||||||
|
you need environment variables to be available when your jobs run, just set
|
||||||
|
them before starting Supercronic itself, and your jobs will inherit them
|
||||||
|
(unless you've used cron before, this is exactly what you expect).
|
||||||
|
|
||||||
|
For example, if you're using Docker, Supercronic
|
||||||
|
|
||||||
|
|
||||||
|
## Logging ##
|
||||||
|
|
||||||
|
Supercronic provides rich logging, and will let you know exactly what command
|
||||||
|
triggered a given message. Here's an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat ./my-crontab
|
||||||
|
*/5 * * * * * * echo "hello from Supercronic"
|
||||||
|
|
||||||
|
$ ./supercronic ./my-crontab
|
||||||
|
INFO[2017-07-10T19:40:44+02:00] read crontab: ./my-crontab
|
||||||
|
INFO[2017-07-10T19:40:50+02:00] starting iteration=0 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
INFO[2017-07-10T19:40:50+02:00] hello from Supercronic channel=stdout iteration=0 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
INFO[2017-07-10T19:40:50+02:00] job succeeded iteration=0 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
INFO[2017-07-10T19:40:55+02:00] starting iteration=1 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
INFO[2017-07-10T19:40:55+02:00] hello from Supercronic channel=stdout iteration=1 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
INFO[2017-07-10T19:40:55+02:00] job succeeded iteration=1 job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Debugging ##
|
||||||
|
|
||||||
|
If your jobs aren't running, or you'd simply like to double-check your crontab
|
||||||
|
syntax, pass the `-debug` flag for more verbose logging:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./supercronic -debug ./my-crontab
|
||||||
|
INFO[2017-07-10T19:43:51+02:00] read crontab: ./my-crontab
|
||||||
|
DEBU[2017-07-10T19:43:51+02:00] try parse(7): */5 * * * * * * echo "hello from Supercronic"[0:15] = */5 * * * * * *
|
||||||
|
DEBU[2017-07-10T19:43:51+02:00] job will run next at 2017-07-10 19:44:00 +0200 CEST job.command="echo "hello from Supercronic"" job.position=0 job.schedule="*/5 * * * * * *"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Duplicate Jobs ##
|
||||||
|
|
||||||
|
Supercronic will wait for a given job to finish before that job is scheduled
|
||||||
|
again (some cron implementations do this, others don't). If a job is falling
|
||||||
|
behind schedule (i.e. it's taking too long to finish), Supercronic will warn
|
||||||
|
you.
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Sleep for 2 seconds every second. This will take too long.
|
||||||
|
* * * * * * * sleep 2
|
||||||
|
|
||||||
|
$ ./supercronic ./my-crontab
|
||||||
|
INFO[2017-07-11T12:24:25+02:00] read crontab: foo
|
||||||
|
INFO[2017-07-11T12:24:27+02:00] starting iteration=0 job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
INFO[2017-07-11T12:24:29+02:00] job succeeded iteration=0 job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
WARN[2017-07-11T12:24:29+02:00] job took too long to run: it should have started 1.009438854s ago job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
INFO[2017-07-11T12:24:30+02:00] starting iteration=1 job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
INFO[2017-07-11T12:24:32+02:00] job succeeded iteration=1 job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
WARN[2017-07-11T12:24:32+02:00] job took too long to run: it should have started 1.014474099s ago job.command="sleep 2" job.position=0 job.schedule="* * * * * * *"
|
||||||
|
```
|
||||||
|
|
||||||
|
[cronexpr]: https://github.com/gorhill/cronexpr
|
Reference in New Issue
Block a user