From 1fa311b2a4b3eb7d14e225c1d53ff5be651f46a8 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sun, 10 Oct 2021 13:17:22 +0100
Subject: [PATCH] Add a simple cron job wrapper script

---
 Dockerfile |  1 +
 README.md  | 23 ++++++-----------------
 every      | 21 +++++++++++++++++++++
 3 files changed, 28 insertions(+), 17 deletions(-)
 create mode 100755 every

diff --git a/Dockerfile b/Dockerfile
index 4a61c01..781fc92 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,6 +6,7 @@ ENV S6_READ_ONLY_ROOT=1 \
 
 COPY etc/ /etc/
 COPY deb_autistici_org.gpg /usr/share/keyrings/deb.autistici.org.gpg
+COPY every /usr/bin/every
 
 ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64.tar.gz /tmp/
 
diff --git a/README.md b/README.md
index 2622b56..e55d90b 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ it is simpler to create a secondary service that will run a loop with
 *sleep*:
 
 ```
-#!/bin/sh -e
+#!/bin/sh
 
 period=600
 
@@ -65,27 +65,16 @@ while true; do
 done
 ```
 
-while the above is ok for short periods, for longer ones (and for more
-resource-intensive jobs) it might be better to wait a random amount of
-time at startup. Consider that "dash" (/bin/sh in Debian) has no
-$RANDOM, so something like this might be necessary:
+To simplify this problem, we ship a simple shell-based "cron job
+runner" that implements a sligthly more sophisticated version of the
+above loop (with random initial delay to stagger jobs on restart)
+called *every*. The above example should then be written like this:
 
 ```
 #!/bin/sh
-
-period=${SCAN_PERIOD_SECS:-86400}
-offset=$(shuf -i 0-${period} -n 1)
-
-sleep $offset
-while true; do
-    /usr/bin/my-command foo bar
-    sleep $period
-done
+exec every 600 /usr/bin/my-command foo bar
 ```
 
-Randomization maximizes the chances that the job will run regularly
-even in face of restarts etc.
-
 ## Differences with stock *s6-overlay*
 
 The base s6-overlay distribution is modified slightly to work around
diff --git a/every b/every
new file mode 100755
index 0000000..8e6f543
--- /dev/null
+++ b/every
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Cron runner for a single job.
+#
+
+if [ $# -lt 2 ]; then
+    echo "Usage: $0 <period> <cmd>..." >&2
+    exit 2
+fi
+
+period="$1"
+shift
+
+# Work around the lack of $RANDOM in dash.
+offset=$(shuf -i 0-${period} -n 1)
+
+sleep ${offset}
+while true; do
+    "$@"
+    sleep ${period}
+done
-- 
GitLab