ADD README / LICENSE

This commit is contained in:
Thomas Orozco
2017-07-10 19:48:23 +02:00
parent 7bf5451157
commit 8fa979c10f
2 changed files with 173 additions and 0 deletions

21
LICENSE.md Normal file
View 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
View 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