• Stars
    star
    198
  • Rank 196,898 (Top 4 %)
  • Language
    C
  • Created about 9 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

run a command at a particular time

snooze: run a command at a particular time

snooze is a new tool for waiting until a particular time and then running a command. Together with a service supervision system such as runit, this can be used to replace cron(8).

snooze has been tested on Linux 4.2. It will likely work on other Unix-like systems with C99.

Benefits

Over cron:

  • mnemonic syntax
  • no overlapping job runs possible
  • filtering by ISO week and day of year
  • due to supervision, no centralized daemon required
  • due to supervision, can easily disable jobs or force their execution instantly
  • due to supervision, have custom logs
  • due to no centralized daemon, no fuzzing with multiple users/permissions
  • very robust with respect to external time changes
  • can use a file timestamp to ensure minimum waiting time between two runs, even across reboots
  • randomized delays (some cron have that)
  • variable slack (no need for anacron)
  • ad-hoc usage possible, just run the program from command line

Over runwhen:

  • less confusing usage (I hope)
  • filtering by ISO week and day of year
  • zero dependencies

Over uschedule:

  • due to supervision, no centralized daemon required
  • filtering by ISO week and day of year

Over systemd timers:

  • mnemonic syntax
  • less complexity for jobs, no need for a <job>.timer file distinct from the <job>.service file,
  • can use a file timestamp to ensure minimum waiting time between two runs, even across reboots
  • very robust with respect to external time changes
  • randomized delays
  • variable slack
  • ad-hoc usage possible, just run the program from command line

Rosetta stone

  • run five minutes after midnight, every day: cron: 5 0 * * * snooze: -M5
  • run at 2:15pm on the first of every month: cron: 15 14 1 * * snooze: -d1 -H14 -M15
  • run at 10 pm on weekdays: cron: 0 22 * * 1-5 snooze: -w1-5 -H22
  • run 23 minutes after midnight, 2am, 4am ..., everyday: cron: 23 0-23/2 * * * snooze: -H/2 -M23
  • run every second week: snooze: -W/2
  • run every 10 days: snooze: -D/10

Usage:

snooze [-nv] [-t timefile] [-T timewait] [-R randdelay] [-s slack] [-d mday] [-m mon] [-w wday] [-D yday] [-W yweek] [-H hour] [-M min] [-S sec] COMMAND...
  • -n: dry-run, print the next 5 times the command would run.
  • -v: verbose, print scheduled (and rescheduled) times.
  • -t, -T: see below timefiles
  • -R: add between 0 and RANDDELAY seconds to the start of the scheduled time.
  • -J: add between 0 and JITTER seconds to scheduled execution time.
  • -s: commands are executed even if they are SLACK (default: 60) seconds late.

The durations RANDDELAY and JITTER and SLACK and TIMEWAIT are parsed as seconds, unless a postfix of m for minutes, h for hours, or d for days is used.

The remaining arguments are patterns for the time fields:

  • -d: day of month
  • -m: month
  • -w: weekday (0-7, sunday is 0 and 7)
  • -D: day of year
  • -W: ISO week of year (0..53)
  • -H: hour
  • -M: minute
  • -S: second

The following syntax is used for these options:

  • exact match: -d 3, run on the 3rd
  • alternation: -d 3,10,27, run on 3rd, 10th, 27th
  • range: -d 1-5, run on 1st, 2nd, 3rd, 4th, 5th
  • star: -d '*', run every day
  • repetition: -d /5, run on 5th, 10th, 15th, 20th, 25th, 30th day
  • shifted repetition: -d 2/5, run on 7th, 12th, 17th, 22nd, 27th day

and combinations of those, e.g. -d 1-10,15/5,28.

The defaults are -d* -m* -w* -D* -W* -H0 -M0 -S0, that is, every midnight.

Note that all patterns need to match (contrary to cron where either day of month or day of week matches), so -w5 -d13 only runs on Friday the 13th.

Timefiles

Optionally, you can keep track of runs in time files, using -t and optionally -T.

When -T is passed, execution will not start earlier than the mtime of TIMEFILE plus TIMEWAIT seconds.

When -T is not passed, snooze will start finding the first matching time starting from the mtime of TIMEFILE, and taking SLACK into account. (E.g. -H0 -s 1d -t timefile will start an instant execution when timefile has not been touched today, whereas without -t this would always wait until next midnight.)

If TIMEFILE does not exist, it will be assumed outdated enough to ensure earliest execution.

snooze does not update the timefiles, your job needs to do that! Only mtime is looked at, so touch(1) is good.

Exact behavior

  • snooze parses the option flags and computes the first time the date pattern matches, as a symbolic date
  • if a timefile is specified, the time is upped to timefile + timewait seconds
  • if a random delay is requested, it is added
  • snooze computes how far this event is in the future
  • snooze sleeps that long, but at most 5 minutes
  • after waking, snooze recomputes how far the event is in the future
  • if the event is in the past, but fewer than SLACK seconds, snooze execs the command. You need to ensure (by setting up supervision) snooze runs again after that!
  • if we woke due to a SIGALRM, the command is executed immediately as well
  • if we notice time moved backwards, recompute the time until the event
  • if the event is in the future, recompute the time it takes, possibly considering shifting of the system time or timezone changes (timezone reload only tested on glibc)
  • If no command was given, just return with status 0
  • and so on...

Common usages

Run a job like cron, every day at 7am and 7pm:

exec snooze -H7,19 rdumpfs / /data/dump/mybox 2>&1

Run a job daily, never twice a day:

exec snooze -H0 -s 1d -t timefile \
	sh -c 'run-parts /etc/cron.daily; touch timefile'

Use snooze inline, run a mirror script every hour at 30 minutes past, but ensure there are at least 20 minutes in between.

set -e
snooze -H'*' -M30 -t timefile -T 20m
touch timefile  # remove this if instantly retrying on failure were ok
mirrorallthethings
touch timefile

Use snooze inline, cron-style mail:

set -e
snooze ...
actualjob >output 2>&1 ||
	mail -s "$(hostname): snooze job failed with status $?" root <output

Snooze for rate-limiting a general purpose runit service: don't restart faster than every two minutes. (Note that after a crash with a daemon runtime of more than two minutes, it will be restarted immediately):

set -e
snooze -H'*' -M'*' -S'*' -t timefile -T 2m
touch timefile
exec mydaemond

Installation

Use make all to build, make install to install relative to PREFIX (/usr/local by default). The DESTDIR convention is respected. You can also just copy the binary into your PATH.

Copyright

snooze is in the public domain.

To the extent possible under law, Leah Neukirchen [email protected] has waived all copyright and related or neighboring rights to this work.

http://creativecommons.org/publicdomain/zero/1.0/

More Repositories

1

nq

Unix command line queue utility
C
2,805
star
2

mblaze

Unix utilities to deal with Maildir
C
451
star
3

styleguide

443
star
4

bacon

a small RSpec clone
Ruby
426
star
5

cwm

portable version of OpenBSD's cwm(1) window manager
C
343
star
6

hrmpf

hrmpf rescue system, built on Void Linux
Shell
299
star
7

xe

simple xargs and apply replacement
C
179
star
8

dosfetch

NeoFetch clone for DOS
Pascal
148
star
9

lr

list files, recursively
C
140
star
10

xtools

a few helpers for working with XBPS
Shell
129
star
11

extrace

trace exec() calls system-wide
C
116
star
12

rum

a gRand Unified Mapper for Rack
Ruby
106
star
13

redo-c

An implementation of the redo build system in portable C with zero dependencies
C
104
star
14

outils

port of some non-standard OpenBSD tools to Linux
C
78
star
15

gitsum

basic darcsum feelalike for Git
Emacs Lisp
67
star
16

ignite

OBSOLETE: use Void Linux
Shell
65
star
17

sabotage

an experimental distribution based on musl libc and busybox
Shell
63
star
18

rdumpfs

a rsync-based dump file system backup tool
Shell
59
star
19

leahutils

description of leahutils
56
star
20

obase

a port of the OpenBSD userland to Linux | unmaintained: use outils
C
51
star
21

colfm

A console, column-oriented file manager
Ruby
46
star
22

fail

crash in various possible ways
C
39
star
23

trivium

Trivium, my minimalist blogging engine
Ruby
39
star
24

rwc

report when files change
C
37
star
25

rps

Ruby Packaging Standard
Ruby
30
star
26

sq

a 7x15 pixel font inspired by Codec and Quadraat Sans Mono
Makefile
30
star
27

knock

Knock is a simplification of the Test Anything Protocol used by Perl and others.
Ruby
29
star
28

te

tiny emacs
C
25
star
29

virtualrb

Virtualize Ruby installations
Ruby
25
star
30

challis

a soft lightweight cloth
Ruby
22
star
31

nb

Nota Bene, a quick note-taking tool for Emacs
Emacs Lisp
22
star
32

notyet

a text-based recursive task tracker
Ruby
20
star
33

tools

various simple tools, not worth a project on their own
Ruby
19
star
34

5x13

a condensed pixel font built on 6x13 ("fixed")
Makefile
18
star
35

wibget

WibGet, a minimalist, but convenient Git web frontend
Ruby
17
star
36

git-merge-pr

apply GitHub pull request from command-line
Shell
17
star
37

libste

C string library based on string ends
C
17
star
38

vuxi

a minimalist static Wiki compiler
Ruby
15
star
39

rdd

random data dumper
C
15
star
40

qed-caltech

C
15
star
41

lywsd03mmc-exporter

a Prometheus exporter for the LYWSD03MMC BLE thermometer
Go
14
star
42

yam

Yam, a functional language running as JavaScript
JavaScript
14
star
43

reap

run process until all its spawned processes are dead
C
14
star
44

necho

minimal, sensible alternatives to echo(1)
C
14
star
45

rup

a sane and simple Ruby package manager
14
star
46

hyx

terminal hex editor
C
13
star
47

signify

portable version of OpenBSD's signify(1) signature tool
C
13
star
48

coma

a console mail user agent | obsolete: use mblaze
Ruby
13
star
49

coset-mirror

(experimental) Mirror of the coset darcs repository
Ruby
12
star
50

tt

a 9term-compatible terminal in Ruby/Tk
Ruby
12
star
51

hittpd

efficient, no-frills HTTP 1.1 server
C
11
star
52

daiquiri

a Rack-based resourceful web framework
11
star
53

wcal

ISO weekly calendar
C
11
star
54

px

search for processes and print top(1)-like status
C
11
star
55

rs

rs(1) β€” reshape a data array (from OpenBSD) | unmaintained: use outils
C
11
star
56

rack-mirror

OUTDATED mirror of Rack's darcs repository, use github.com/chneukirchen/rack
Ruby
10
star
57

amok

a compact mock library
Ruby
9
star
58

rubyports

Hookin-based RubyPorts system
Ruby
9
star
59

xlossage

display pressed keys in X11 in a readable way
C
8
star
60

arr

(re)arrange and select fields on each line
Groff
8
star
61

rnl

remove trailing newlines
Shell
8
star
62

sgn

pseudonymous digital signatures
Emacs Lisp
7
star
63

ji

a minimalist forum software
Ruby
7
star
64

vmenu

personal fork of vis-menu/slmenu
C
7
star
65

revisit

a TODO list for the future
Ruby
7
star
66

clitter

a ncurses twitter client
Ruby
7
star
67

schell

a lispy shell scripting language
Scheme
7
star
68

htping

periodically send HTTP requests
Go
7
star
69

netpbm-mirror

git-svn mirror of netpbm (updated manually)
C
6
star
70

mlog

merge log files by timestamp
C
6
star
71

listening

check if a TCP server is listening
C
5
star
72

snowcat

encrypted data streams over sockets
Go
5
star
73

atxec

run command expanding arguments from file or environment
Perl
5
star
74

adventofcode2019

Advent of Code (adventofcode.com) in k and Perl 5
Perl
5
star
75

musl-chris2

my sandbox for playing with musl
C
5
star
76

lrep

literate read-eval-print
Ruby
5
star
77

adventofcode2022

Advent of Code 2022 in Racket and Zig.
Racket
4
star
78

rexample

Ruby
4
star
79

holes

find runs of zero bytes
C
4
star
80

tap3

check output/error/status of a command against a specification
Perl
4
star
81

btac

print file in reverse order
C
4
star
82

rmeta

a OMeta implementation for Ruby
4
star
83

sson

S-Expression Standard Object Notation
Ruby
4
star
84

adventofcode2015

Advent of Code (adventofcode.com) in K
Ruby
4
star
85

noir

a new programming language
JavaScript
4
star
86

dwm-chris2

Personal dwm fork.
C
3
star
87

parseopt

a collection of command line argument parsers
Shell
3
star
88

rc

C
3
star
89

xdu

display the output of "du" in an X window
C
3
star
90

pds

parallel data substitution
Ruby
3
star
91

adventofcode2020

Advent of Code 2020 (adventofcode.com) in J and Clojure
Clojure
3
star
92

ulidgen

generate or tag lines with ULID
C
2
star
93

gleam-codespace

A codespace to work with Gleam
Dockerfile
2
star
94

actions-archive-all

generate tarballs including submodules from GitHub Actions
Shell
2
star
95

docker-lab-bgp

A small BGP lab in Docker
2
star
96

literate-janet

Makefile
2
star
97

adventofcode2021

Advent of Code 2021 (adventofcode.com) in BQN and Clojure
Clojure
2
star
98

adventofcode2017

adventofcode.com 2017
C++
2
star
99

conference-sponsors

Conference Sponsor tracking
2
star
100

systas

Systas Scheme (archival copy)
C
2
star