Deployment
Jobber is written in Go, and it should be possible to compile and run it on any Unix/Linux system.
Note that, although Jobber can be used instead of cron, it is certainly possible to run both at the same time.
Installation from a Package
The easiest way to install Jobber is via a binary package.
Compilation and Installation from Source
Instead of installing a binary package, you can certainly compile and install Jobber yourself.
You need a recent version of Go to compile Jobber. So, install Go, pick a place for your workspace (say, /path/to/your/workspace), and ensure that the environment variable “GOPATH” includes a path to your workspace. Then:
cd /path/to/your/workspace go get github.com/dshearer/jobber cd src/github.com/dshearer/jobber git checkout v1.2 make GO_WKSPC=/path/to/your/workspace
Jobber consists of two binaries: jobber and jobberd. jobberd is a daemon that runs jobs; jobber is a client with which the user can interact with jobbberd. After compiling, you’ll find them in /path/to/your/workspace/bin.
Now:
- Make a new, non-login user called “jobber_client”.
- Change jobber’s permissions to 04755, and its owner to jobber_client:root.
- Change jobberd’s permissions to 0755, and its owner to root:root.
- Move jobber and jobberd someplace more appropriate (e.g., /usr/local/bin and /usr/local/libexec respectively).
- Ensure that jobberd will get started when your computer boots. Note that jobberd does not daemonize itself — you will need to run it with something like daemonize(1).
Defining Jobs
As with cron, each user can have its own set of jobs, which will be run under that user’s privileges. A user’s jobs are defined in a jobfile — a file named “.jobber” in the user’s home directory. Here's an example that defines two jobs:
[prefs] notifyProgram: /home/foobar/handleError.sh [jobs] - name: DailyBackup cmd: backup daily time: 0 0 13 onError: Stop notifyOnError: true notifyOnFailure: false - name: OffsiteBackup cmd: | mount /backup/offsite mount /backup/linux/weekly backup-offsite /backup/linux/weekly/backup-0 linux || exit 1 umount /backup/linux/weekly umount /backup/offsite time: 0 0 14 * * 1 onError: Stop
As shown, there are two sections:
prefs
and
jobs
. The contents of both sections are YAML
documents.
Section
prefs
This section sets general preferences for how Jobber runs this user’s jobs. At this time, there is only one valid field.
Field | Value | Default Value |
---|---|---|
notifyProgram |
A path to an executable file. When this field is set, jobs that notify on error or failure do so by executing the specified file. See below for details. When it is not set, they notify by sending an email to the owning user, using sendmail. |
None. |
Section
jobs
This section defines the user’s jobs.
As stated above, this section must contain a YAML file that defines a sequence of mappings. Each mapping in this sequence defines a job.
The fields of a job definition:
Field | Value | Default Value |
---|---|---|
name |
The name of the job. | N/A |
cmd |
A shell script that is executed when this job runs. Jobber will use the shell at /bin/sh. | N/A |
time |
A string specifying when the job should run. See below for details. | * * * * * * |
onError |
A string (Stop , Backoff , or Continue )
specifying what should happen when the job has an error. See below for details.
|
Continue |
notifyOnError |
A string (true or false ) specifying
whether jobberd should notify when the job has an error. See below for details.
|
false |
notifyOnFailure |
A string (true or false ) specifying
whether jobberd should notify when the job fails. See below for details.
|
true |
Time Strings
Field
time
specifies the schedule at which a job is run, in a manner similar to how
cron jobs’ schedules are specified: with a space-separated list of up
to six specifiers, each one of which constrains a different component of
time (second, minute, hour, etc.). Schematically:
sec min hour month_day month week_day
A job is scheduled thus: it will run at any time that satisfies all of the specifiers sec, min, hour, and month and one of the specifiers month_day and week_day.
Each specifier can take one of the following forms: (“a”, “b”, “c”, and “n” are placeholders for arbitrary numerals.)
Specifier Form | What It Matches |
---|---|
* |
Any value |
a |
The value a |
*/n |
Every n-th value — e.g., */25 in the sec
specifier would match 0, 25, and 50, whereas in the month specifier it
would match 1 and 26.
|
a,b,c,... |
The values a, b, c, ... |
a-b |
Any of the values between and including a and b |
The specifiers have different permitted values for the placeholders in the specifier forms:
Specifier | Values for “a”, “b”, and “c” | Values for “n” |
---|---|---|
sec | 0 thru 59 |
1 thru 59 |
min | 0 thru 59 |
1 thru 59 |
hour | 0 thru 23 |
1 thru 23 |
month_day | 1 thru 31 |
1 thru 30 |
month | 1 thru 12 |
1 thru 11 |
week_day | 0 (Sunday) thru 6 (Saturday) |
1 thru 5 |
Error-handling
Some terms: When Jobber runs a job and that job exits with a non-0 status, we call that a job error. When Jobber stops scheduling runs of a job due to one or more job errors, we call that a job failure.
In the
onError
field in the job’s definition, you can control what Jobber does after
a job error by picking one of these values:
Value | Effect |
---|---|
Stop |
Stop scheduling runs of this job. |
Backoff |
Schedule runs of this job according to an exponential backoff algorithm. If a later run of the job succeeds, jobber resumes scheduling this job normally; but if the job errors again on several consecutive runs, Jobber stops scheduling it. |
Continue |
Continue scheduling this job normally. |
If you would like Jobber to notify you when a job errors or fails, first set
notifyOnError
or
notifyOnFailure
to
true
in the job’s definition in the Jobber file.
Then, write a notify program — a program that does whatever
logic you want done after an error or failure. Set the
notifyProgram
field in the
prefs
section of the Jobber file to the path to your notify program.
When Jobber calls your notify program, it will write to stdin a JSON document like this:
{ "job":{ "command":"/home/dylan/some_program", "name":"MyHourlyJob", "notifyOnError":true, "notifyOnFailure":false, "onError":"Stop", "status":"Failed", "time":"0 0 * * * *" }, "startTime":"May 29 15:25:10 2017", "stderr":"Some errors\n", "stderr_base64":false, "stdout":"Quotes: \"adf\"\n", "stdout_base64":false, "succeeded":false, "user":"dylan" }
The fields in the
job
object are from the job’s definition, except for
status
, which contains
Good
,
Backoff
, or
Failed
.
stdout
(respectively,
stderr
) contains whatever the job wrote to stdout (stderr). If
stdout_base64
contains
true
, then the job wrote only UTF-8 bytes to stdout (stderr), and
stdout
(
stderr
) contains a string with those bytes; otherwise, there were some non-UTF-8
bytes and
stdout
(
stderr
) contains a Base64 encoding of the output.
Loading Jobs
After you've created a user’s jobfile, log in as that user and do:
jobber reload
You can also reload all users’ jobfiles by logging in as root and doing:
jobber reload -a
Listing Jobs
You can list the jobs for a particular user by logging in as that user and doing
jobber list
This command also shows you the status of each job — that is, whether the job is being scheduled as normal, the exponential backoff algorithm is being applied, or the job has failed.
As with the
reload
command, you can do the same for all users by adding the
-a
option as root.
Listing Runs
You can see a list of recent runs of any jobs for a particular user by logging in as that user and doing
jobber log
As with the other commands, you can do the same for all users by adding the
-a
option as root.
Testing Jobs
If you'd like to test out a job, do
jobber test JOB_NAME
Jobber will immediately run that job, tell you whether it succeeded, and show you its output.