mirror of
https://github.com/yavook/kiwi-cron.git
synced 2024-11-24 00:13:00 +00:00
Merge branch 'release/0.2.0'
This commit is contained in:
commit
6f48f18c01
8 changed files with 81 additions and 69 deletions
|
@ -1,4 +1,5 @@
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
LABEL maintainer="jmm@yavook.de"
|
||||||
|
|
||||||
ENV TZ=Etc/UTC
|
ENV TZ=Etc/UTC
|
||||||
|
|
||||||
|
|
24
README.md
24
README.md
|
@ -14,6 +14,12 @@ Just drop your scripts into the relevant directory under `/kiwi-cron`, that's it
|
||||||
You will likely want to automate some tasks regarding your `docker` infrastructure.
|
You will likely want to automate some tasks regarding your `docker` infrastructure.
|
||||||
That's why the `kiwi-cron` images package a current `docker-cli` – you can just mount your `docker.sock` in its containers and use `docker` commands normally.
|
That's why the `kiwi-cron` images package a current `docker-cli` – you can just mount your `docker.sock` in its containers and use `docker` commands normally.
|
||||||
|
|
||||||
|
## Time Zones
|
||||||
|
|
||||||
|
`kiwi-cron` images include the `tzdata` package and automatically handle `/etc/localtime` on startup. By default, "Etc/UTC" is set as the container time zone.
|
||||||
|
|
||||||
|
To use a different time zone, change the container environment variable `TZ` to your liking, e.g. "Europe/Berlin".
|
||||||
|
|
||||||
## Simple jobs
|
## Simple jobs
|
||||||
|
|
||||||
On startup, `kiwi-cron` checks for possible job files in the `/kiwi-cron` directory structure.
|
On startup, `kiwi-cron` checks for possible job files in the `/kiwi-cron` directory structure.
|
||||||
|
@ -21,27 +27,21 @@ On startup, `kiwi-cron` checks for possible job files in the `/kiwi-cron` direct
|
||||||
For each subdirectory, a random valid cron schedule is generated, so that:
|
For each subdirectory, a random valid cron schedule is generated, so that:
|
||||||
|
|
||||||
- `/kiwi-cron/hourly` runs once every hour (random minute)
|
- `/kiwi-cron/hourly` runs once every hour (random minute)
|
||||||
- `/kiwi-cron/daily` runs once every day (random nighttime value)
|
- `/kiwi-cron/daily` runs once every day (random nighttime value between 9 pm and 3 am)
|
||||||
- `/kiwi-cron/weekly` runs once every weekend (random nighttime value on Saturday or Sunday)
|
- `/kiwi-cron/weekly` runs once every weekend (random nighttime value on Saturday or Sunday)
|
||||||
- `/kiwi-cron/monthly` runs once every month (random nighttime value on a random day)
|
- `/kiwi-cron/monthly` runs once every month (random nighttime value on a random day <= 28)
|
||||||
- `/kiwi-cron/yearly` and `/kiwi-cron/annually` runs once a year (random nighttime value on a random day in January or February)
|
- `/kiwi-cron/yearly` and `/kiwi-cron/annually` runs once a year (random nighttime value on a random day <= 28 in January or February)
|
||||||
|
|
||||||
Cron schedules are regenerated once on each startup, only for directories that have files.
|
Cron schedules are regenerated once on each startup, only for directories that have files.
|
||||||
|
|
||||||
## Time Zones
|
## Granularity: The `/kiwi-cron/every` directory
|
||||||
|
|
||||||
`kiwi-cron` images include the `tzdata` package and automatically handle `/etc/localtime` on startup. By default, "Etc/UTC" is set as the container time zone.
|
|
||||||
|
|
||||||
To use a different time zone, change the container environment variable `TZ` to your liking, e.g. "Europe/Berlin".
|
|
||||||
|
|
||||||
## Finer granularity: The `/kiwi-cron/every` directory
|
|
||||||
|
|
||||||
Directories like `/kiwi-cron/every/5_minutes` will run scripts every 5 minutes.
|
Directories like `/kiwi-cron/every/5_minutes` will run scripts every 5 minutes.
|
||||||
`kiwi-cron` picks up on that format and generates valid `cron` schedules on startup.
|
`kiwi-cron` picks up on that format and generates valid `cron` schedules on startup.
|
||||||
|
|
||||||
You can define schedules to be run every N minutes, hours, days, or months by creating the corresponding directories.
|
This way, you can define schedules to be run every N minutes, hours, days, or months by creating the corresponding directories.
|
||||||
|
|
||||||
Scheduling for every N weeks (or years) doesn't work that way; jobs in those directories will instead be run every week (or every year).
|
Scheduling for every N weeks (or years) doesn't work though; jobs in those directories will instead be run every week (or every year).
|
||||||
|
|
||||||
## Inspection
|
## Inspection
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
exec /usr/local/libexec/kiwi-cron/run_cron \
|
exec /usr/local/libexec/kiwi-cron/run_cron \
|
||||||
"${@}" \
|
"${@}" \
|
||||||
/usr/local/libexec/kiwi-cron/schedule_dirs
|
/usr/local/libexec/kiwi-cron/scheduler
|
||||||
|
|
|
@ -4,50 +4,29 @@ cs_every="${1:-1}"
|
||||||
cs_units="${2}"
|
cs_units="${2}"
|
||||||
cs_command="${3}"
|
cs_command="${3}"
|
||||||
|
|
||||||
if [ "${cs_every}" -eq 1 ]; then
|
if [ "${cs_every}" = "1" ]; then
|
||||||
cs_every=""
|
cs_every="*"
|
||||||
else
|
else
|
||||||
cs_every="/${cs_every}"
|
cs_every="*/${cs_every}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# generate valid random schedule values
|
|
||||||
# generally, "nighttime" and "weekend" will be preferred.
|
|
||||||
|
|
||||||
# shellcheck disable=SC3028 # RANDOM is defined in alpine's /bin/sh
|
|
||||||
cs_rand_min=$(( RANDOM % 60 ))
|
|
||||||
|
|
||||||
# shellcheck disable=SC3028
|
|
||||||
# cs_rand_hour=$(( RANDOM % 24 ))
|
|
||||||
cs_rand_hour=$(( (21 + RANDOM % 7) % 24 ))
|
|
||||||
|
|
||||||
# shellcheck disable=SC3028
|
|
||||||
cs_rand_day=$(( RANDOM % 31 + 1 ))
|
|
||||||
|
|
||||||
# shellcheck disable=SC3028
|
|
||||||
# cs_rand_weekday=$(( RANDOM % 7 ))
|
|
||||||
cs_rand_weekday=$(( (6 + RANDOM % 2) % 7 ))
|
|
||||||
|
|
||||||
# shellcheck disable=SC3028
|
|
||||||
# cs_rand_month=$(( RANDOM % 12 + 1 ))
|
|
||||||
cs_rand_month=$(( RANDOM % 2 + 1 ))
|
|
||||||
|
|
||||||
case "${cs_units}" in
|
case "${cs_units}" in
|
||||||
minute)
|
minute)
|
||||||
echo "*${cs_every}" "*" "*" "*" "*" "${cs_command}"
|
echo "${cs_every} * * * * ${cs_command}"
|
||||||
;;
|
;;
|
||||||
hour)
|
hour)
|
||||||
echo "${cs_rand_min}" "*${cs_every}" "*" "*" "*" "${cs_command}"
|
echo "R ${cs_every} * * * ${cs_command}"
|
||||||
;;
|
;;
|
||||||
day)
|
day)
|
||||||
echo "${cs_rand_min}" "${cs_rand_hour}" "*${cs_every}" "*" "*" "${cs_command}"
|
echo "R R ${cs_every} * * ${cs_command}"
|
||||||
;;
|
;;
|
||||||
week)
|
week)
|
||||||
echo "${cs_rand_min}" "${cs_rand_hour}" "*" "*" "${cs_rand_weekday}" "${cs_command}"
|
echo "R R * * R ${cs_command}"
|
||||||
;;
|
;;
|
||||||
month)
|
month)
|
||||||
echo "${cs_rand_min}" "${cs_rand_hour}" "${cs_rand_day}" "*${cs_every}" "*" "${cs_command}"
|
echo "R R R ${cs_every} * ${cs_command}"
|
||||||
;;
|
;;
|
||||||
year)
|
year)
|
||||||
echo "${cs_rand_min}" "${cs_rand_hour}" "${cs_rand_day}" "${cs_rand_month}" "*" "${cs_command}"
|
echo "R R R R * ${cs_command}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,28 +1,16 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
print_cron_schedule () {
|
|
||||||
pcs_minute="${1}"
|
|
||||||
pcs_hour="${2}"
|
|
||||||
pcs_day="${3}"
|
|
||||||
pcs_month="${4}"
|
|
||||||
pcs_weekday="${5}"
|
|
||||||
pcs_command="${6}"
|
|
||||||
|
|
||||||
printf '%-8s%-8s%-8s%-8s%-8s%s\n' \
|
|
||||||
"${pcs_minute}" "${pcs_hour}" "${pcs_day}" "${pcs_month}" "${pcs_weekday}" "${pcs_command}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# header
|
# header
|
||||||
echo '# crontab generated by kiwi-cron'
|
echo '# crontab generated by kiwi-cron'
|
||||||
echo '# generation time: '"$(date)"
|
echo '# generation time: '"$(date)"
|
||||||
echo '#'
|
echo '#'
|
||||||
|
|
||||||
# short documentation line
|
# short documentation line
|
||||||
print_cron_schedule \
|
printf '%-8s%-8s%-8s%-8s%-8s%s\n' \
|
||||||
"# min" "hour" "day" "month" "weekday" "command"
|
"# min" "hour" "day" "month" "weekday" "command"
|
||||||
|
|
||||||
# schedules
|
# schedules
|
||||||
while read -r pc_min pc_hour pc_day pc_month pc_weekday pc_command; do
|
while read -r pc_minute pc_hour pc_day pc_month pc_weekday pc_command; do
|
||||||
print_cron_schedule \
|
printf '%-8s%-8s%-8s%-8s%-8s%s\n' \
|
||||||
"${pc_min}" "${pc_hour}" "${pc_day}" "${pc_month}" "${pc_weekday}" "${pc_command}"
|
"${pc_minute}" "${pc_hour}" "${pc_day}" "${pc_month}" "${pc_weekday}" "${pc_command}"
|
||||||
done
|
done
|
||||||
|
|
25
libexec/kiwi-cron/randomize_schedule
Executable file
25
libexec/kiwi-cron/randomize_schedule
Executable file
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028 # RANDOM is defined in alpine's /bin/sh
|
||||||
|
|
||||||
|
read -r rs_minute rs_hour rs_day rs_month rs_weekday rs_command
|
||||||
|
|
||||||
|
[ "${rs_minute}" = "R" ] && \
|
||||||
|
rs_minute=$(( RANDOM % 60 ))
|
||||||
|
|
||||||
|
[ "${rs_hour}" = "R" ] && \
|
||||||
|
rs_hour=$(( (21 + RANDOM % 6) % 24 )) # prefer nighttime
|
||||||
|
# rs_hour=$(( RANDOM % 24 )) # don't prefer nighttime
|
||||||
|
|
||||||
|
[ "${rs_day}" = "R" ] && \
|
||||||
|
rs_day=$(( RANDOM % 28 + 1 )) # don't mess with February 31st
|
||||||
|
|
||||||
|
[ "${rs_month}" = "R" ] && \
|
||||||
|
rs_month=$(( RANDOM % 2 + 1 )) # prefer January & February
|
||||||
|
# rs_month=$(( RANDOM % 12 + 1 )) # don't prefer January & February
|
||||||
|
|
||||||
|
[ "${rs_weekday}" = "R" ] && \
|
||||||
|
rs_weekday=$(( (6 + RANDOM % 2) % 7 )) # prefer weekends
|
||||||
|
# rs_weekday=$(( RANDOM % 7 )) # don't prefer weekends
|
||||||
|
|
||||||
|
echo "${rs_minute} ${rs_hour} ${rs_day} ${rs_month} ${rs_weekday} ${rs_command}"
|
|
@ -1,5 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# commands
|
||||||
|
crond_exe="$(command -v crond)"
|
||||||
|
|
||||||
# set timezone
|
# set timezone
|
||||||
export TZ="${TZ:-Etc/UTC}"
|
export TZ="${TZ:-Etc/UTC}"
|
||||||
ln -sf "/usr/share/zoneinfo/${TZ}" "/etc/localtime"
|
ln -sf "/usr/share/zoneinfo/${TZ}" "/etc/localtime"
|
||||||
|
@ -22,7 +25,6 @@ shift "$(( OPTIND - 1 ))"
|
||||||
# CLI arguments
|
# CLI arguments
|
||||||
rc_executable="${1}"
|
rc_executable="${1}"
|
||||||
|
|
||||||
|
|
||||||
if [ -n "${rc_dry_run}" ]; then
|
if [ -n "${rc_dry_run}" ]; then
|
||||||
# verbose, dry run
|
# verbose, dry run
|
||||||
set -x
|
set -x
|
||||||
|
@ -39,6 +41,6 @@ fi
|
||||||
| crontab -
|
| crontab -
|
||||||
|
|
||||||
# hand over to crond
|
# hand over to crond
|
||||||
exec crond -fd 8
|
exec "${crond_exe}" -fd 8
|
||||||
|
|
||||||
exit 0
|
exit 0
|
|
@ -1,5 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# shellcheck disable=SC3001 # process substitution are defined in alpine's /bin/sh
|
||||||
|
|
||||||
this_script="$( readlink -f "${0}" )"
|
this_script="$( readlink -f "${0}" )"
|
||||||
this_dir="${this_script%/*}"
|
this_dir="${this_script%/*}"
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ schedule_dirs="$(
|
||||||
)"
|
)"
|
||||||
|
|
||||||
for schedule_dir in ${schedule_dirs}; do
|
for schedule_dir in ${schedule_dirs}; do
|
||||||
# ignore if no files
|
# ignore dirs without files
|
||||||
if dir_has_no_files "${schedule_dir}"; then
|
if dir_has_no_files "${schedule_dir}"; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -52,7 +54,9 @@ for schedule_dir in ${schedule_dirs}; do
|
||||||
units="${dir_name%ly}"
|
units="${dir_name%ly}"
|
||||||
units="$( dir_to_unit "${units}" )"
|
units="$( dir_to_unit "${units}" )"
|
||||||
|
|
||||||
"${this_dir}/create_schedule" "1" "${units}" "run-parts '${schedule_dir}'"
|
"${this_dir}/create_schedule" \
|
||||||
|
"1" "${units}" "run-parts '${schedule_dir}'" \
|
||||||
|
| "${this_dir}/randomize_schedule"
|
||||||
done
|
done
|
||||||
|
|
||||||
# check dirs in "/kiwi-cron/every" directory
|
# check dirs in "/kiwi-cron/every" directory
|
||||||
|
@ -61,16 +65,29 @@ every_schedule_dirs="$(
|
||||||
)"
|
)"
|
||||||
|
|
||||||
for schedule_dir in ${every_schedule_dirs}; do
|
for schedule_dir in ${every_schedule_dirs}; do
|
||||||
# ignore if no files
|
# ignore dirs without files
|
||||||
if dir_has_no_files "${schedule_dir}"; then
|
if dir_has_no_files "${schedule_dir}"; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# infer schedule params by directory name
|
# infer schedule params by directory name
|
||||||
dir_name="${schedule_dir##*/}"
|
dir_name="${schedule_dir##*/}"
|
||||||
every="$( echo "${dir_name}" | awk -F_ '{print $1}' )"
|
case "${dir_name}" in
|
||||||
units="$( echo "${dir_name}" | awk -F_ '{print $2}' )"
|
*_*) # looks like: every/5_minutes
|
||||||
|
read -r every units < \
|
||||||
|
<( echo "${dir_name}" | tr '_' ' ' )
|
||||||
|
;;
|
||||||
|
|
||||||
|
*) # probably looks like: every/day
|
||||||
|
every="1"
|
||||||
|
units="${dir_name}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# remove trailing "s" if present
|
||||||
units="${units%s}"
|
units="${units%s}"
|
||||||
|
|
||||||
"${this_dir}/create_schedule" "${every}" "${units}" "run-parts '${schedule_dir}'"
|
"${this_dir}/create_schedule" \
|
||||||
|
"${every}" "${units}" "run-parts '${schedule_dir}'" \
|
||||||
|
| "${this_dir}/randomize_schedule"
|
||||||
done
|
done
|
Loading…
Reference in a new issue