1
0
Fork 0
mirror of https://github.com/notwa/rc synced 2024-12-21 21:49:40 -08:00
rc/sh/minutemaid

63 lines
2.1 KiB
Bash
Executable file

#!/usr/bin/env dash
# compat: +ash +bash +dash -hush -ksh +mksh +oksh +osh +posh +yash +zsh
minutemaid() { ### @-
### check if the current minute is divisible by a given number,
### and optionally execute a command if it is. if a command is given,
### either execute the command and return its exit value,
### or execute nothing and return 0. if a command is omitted,
### either return 0 on the minute, or return 1.
###
### note that a "minute" is relative to the seconds since the epoch,
### not the minute of the hour. this ensures that commands will run
### roughly every N minutes, regardless of the minute hand on the clock.
###
### note that `minutemaid 1` will always return 0,
### and `minutemaid 1 command` will always execute the command,
### since every integral interval is evenly divisible by 1.
### `minutemaid 0`, and any negative interval, is an error.
###
### ```
### # crontab usage:
### * * * * * minutemaid 9 ~/work/do_my_bidding # runs every nine minutes
### # loop usage:
### until minutemaid 9; do sleep 5; done
### echo the wait is finally over; date
### # improper usage:
### while minutemaid 1; do sleep 1; done
### echo this will never happen
### ```
local offset=0 name=
while getopts 'o:h' name; do
case $name in
o) offset="$OPTARG";;
?) local fd=0 # FIXME: this also matches single-character filenames!
[ $name = h ] && fd=1 || fd=2
printf '%s\n' "usage: $0 [-o offset] {interval} [{command} [{args...}]]" >&$fd
[ $name = h ] && return 0 || return 1;;
esac
done
shift $((OPTIND-1))
local interval="${1:?no interval specified}"
shift
if [ "$interval" -gt 0 ] 2>/dev/null; then
:
else
printf "%s\n" "$0: interval must be a positive integer" >&2
return 1
fi
local sec="$(date +%s)"
local min="$((sec/60+offset))"
local mod="$((min%interval))"
if [ $# -gt 0 ]; then
[ $mod -ne 0 ] || "$@"
else
[ $mod -eq 0 ] && return 0 || return 1
fi
}
[ -n "${preload+-}" ] || minutemaid "$@"