mirror of
https://github.com/yavook/kiwi-cron.git
synced 2024-11-23 16:03:01 +00:00
refactoring + README
This commit is contained in:
parent
8031e3845d
commit
e0d9dd6602
4 changed files with 203 additions and 164 deletions
|
@ -18,6 +18,6 @@ RUN set -ex; \
|
||||||
docker-cli \
|
docker-cli \
|
||||||
;
|
;
|
||||||
|
|
||||||
COPY cron-exec /usr/local/bin/
|
COPY kiwi-cron /usr/local/bin/
|
||||||
|
|
||||||
CMD [ "cron-exec" ]
|
CMD [ "kiwi-cron" ]
|
40
README.md
40
README.md
|
@ -8,18 +8,36 @@ Simple cron-jobs for [`kiwi-scp`](https://github.com/ldericher/kiwi-scp)
|
||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
kiwi-cron comes with a pre-configured cron daemon for periodic jobs.
|
`kiwi-cron` comes with a (slightly) opinionated `cron` daemon config for periodic jobs.
|
||||||
Just drop your scripts into the relevant directory under `/kiwi-cron/` and that's it.
|
Just drop your scripts into the relevant directory under `/kiwi-cron`, that's it.
|
||||||
|
|
||||||
- `/kiwi-cron/hourly` – is run every full hour
|
You will likely want to automate some tasks regarding your `docker` infrastructure.
|
||||||
- `/kiwi-cron/daily` – is run every day at 2 am
|
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.
|
||||||
- `/kiwi-cron/weekly` – is run every saturday at 3 am
|
|
||||||
- `/kiwi-cron/monthly` – is run on the first day of every month at 5 am
|
|
||||||
- `/kiwi-cron/yearly` and `/kiwi-cron/annually` – is run on every January 1st at 12 am
|
|
||||||
|
|
||||||
## `/kiwi-cron/every` directory
|
## Simple jobs
|
||||||
|
|
||||||
You can use directories like `/kiwi-cron/every/5_minutes` to run scripts every 5 minutes.
|
On startup, `kiwi-cron` checks for possible job files in the `/kiwi-cron` directory structure.
|
||||||
`kiwi-cron` automatically picks up on that format and generates cron schedules for you.
|
|
||||||
|
|
||||||
You can define schedules to be run every N minutes, hours, days, or months that way.
|
For each subdirectory, a random valid cron schedule is generated, so that:
|
||||||
|
|
||||||
|
- `/kiwi-cron/hourly` runs once every hour (random minute)
|
||||||
|
- `/kiwi-cron/daily` runs once every day (random nighttime value)
|
||||||
|
- `/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/yearly` and `/kiwi-cron/annually` runs once a year (random nighttime value on a random day in January or February)
|
||||||
|
|
||||||
|
Cron schedules are regenerated once on each startup, only for directories that have files.
|
||||||
|
|
||||||
|
## Finer granularity: The `/kiwi-cron/every` directory
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
## Inspection
|
||||||
|
|
||||||
|
Checking the generated `cron` schedules is done using the standard `crontab` command:
|
||||||
|
`docker exec kiwi-cron-container crontab -l` will show the effective schedules.
|
||||||
|
|
151
cron-exec
151
cron-exec
|
@ -1,151 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
crontab_append () {
|
|
||||||
crontab="$(
|
|
||||||
printf '%s\n%s' \
|
|
||||||
"${crontab}" "${1}"
|
|
||||||
)"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_cron_schedule() {
|
|
||||||
cas_min="${1}"
|
|
||||||
cas_hour="${2}"
|
|
||||||
cas_day="${3}"
|
|
||||||
cas_month="${4}"
|
|
||||||
cas_weekday="${5}"
|
|
||||||
cas_command="${6}"
|
|
||||||
|
|
||||||
printf '%-8s%-8s%-8s%-8s%-8s%s\n' \
|
|
||||||
"${cas_min}" "${cas_hour}" "${cas_day}" "${cas_month}" "${cas_weekday}" "${cas_command}"
|
|
||||||
}
|
|
||||||
|
|
||||||
crontab='# crontab generated for kiwi-cron'
|
|
||||||
crontab_append '# generation time: '"$(date)"
|
|
||||||
crontab_append '#'
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"# min" "hour" "day" "month" "weekday" "command"
|
|
||||||
)"
|
|
||||||
|
|
||||||
# check *ly dirs in root directory
|
|
||||||
schedule_dirs="$(
|
|
||||||
find "/kiwi-cron" -type d -name "*ly" -mindepth 1 -maxdepth 1
|
|
||||||
)"
|
|
||||||
|
|
||||||
for schedule_dir in ${schedule_dirs}; do
|
|
||||||
# count files in scheduler directory
|
|
||||||
schedule_filecount="$(
|
|
||||||
find "${schedule_dir}" -type f -mindepth 1 -maxdepth 1 \
|
|
||||||
| wc -l
|
|
||||||
)"
|
|
||||||
|
|
||||||
# ignore if empty
|
|
||||||
if [ "${schedule_filecount}" -eq "0" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# infer cron schedule by directory name
|
|
||||||
units="${schedule_dir##*/}"
|
|
||||||
|
|
||||||
case "${units}" in
|
|
||||||
hourly)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"0" "*" "*" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
daily)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"0" "2" "*" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
weekly)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"0" "3" "*" "*" "6" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
monthly)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"0" "5" "1" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
yearly|annually)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"0" "0" "1" "1" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# check dirs in "every" subdirectory
|
|
||||||
every_schedule_dirs="$(
|
|
||||||
find "/kiwi-cron/every" -type d -mindepth 1 -maxdepth 1
|
|
||||||
)"
|
|
||||||
|
|
||||||
for schedule_dir in ${every_schedule_dirs}; do
|
|
||||||
# count files in scheduler directory
|
|
||||||
schedule_filecount="$(
|
|
||||||
find "${schedule_dir}" -type f -mindepth 1 -maxdepth 1 \
|
|
||||||
| wc -l
|
|
||||||
)"
|
|
||||||
|
|
||||||
# ignore if empty
|
|
||||||
if [ "${schedule_filecount}" -eq "0" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# infer cron schedule by directory name
|
|
||||||
schedule="${schedule_dir##*/}"
|
|
||||||
every="$( echo "${schedule}" | awk -F_ '{print $1}' )"
|
|
||||||
units="$( echo "${schedule}" | awk -F_ '{print $2}' )"
|
|
||||||
units="${units%s}"
|
|
||||||
|
|
||||||
# generate valid random values
|
|
||||||
rand_min=$(( RANDOM % 60 ))
|
|
||||||
# rand_hour=$(( RANDOM % 24 ))
|
|
||||||
# generating nighttime values seems like a good idea!
|
|
||||||
rand_hour=$(( (RANDOM % 7 + 21) % 24 ))
|
|
||||||
rand_day=$(( RANDOM % 31 + 1 ))
|
|
||||||
|
|
||||||
case "${units}" in
|
|
||||||
minute)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"*/${every}" "*" "*" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
hour)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"${rand_min}" "*/${every}" "*" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
day)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"${rand_min}" "${rand_hour}" "*/${every}" "*" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
|
|
||||||
month)
|
|
||||||
crontab_append "$(
|
|
||||||
print_cron_schedule \
|
|
||||||
"${rand_min}" "${rand_hour}" "${rand_day}" "*/${every}" "*" "run-parts '${schedule_dir}'"
|
|
||||||
)"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# replace crontab
|
|
||||||
echo "${crontab}" | crontab -
|
|
||||||
exec crond -fd 8
|
|
172
kiwi-cron
Executable file
172
kiwi-cron
Executable file
|
@ -0,0 +1,172 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
crontab=''
|
||||||
|
crontab_line () {
|
||||||
|
if [ -z "${crontab}" ]; then
|
||||||
|
crontab="${1}"
|
||||||
|
else
|
||||||
|
crontab="$(
|
||||||
|
printf '%s\n%s' "${crontab}" "${1}";
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_cron_schedule() {
|
||||||
|
pcs_min="${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_min}" "${pcs_hour}" "${pcs_day}" "${pcs_month}" "${pcs_weekday}" "${pcs_command}"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_schedule() {
|
||||||
|
cs_every="${1:-1}"
|
||||||
|
cs_units="${2}"
|
||||||
|
cs_command="${3}"
|
||||||
|
|
||||||
|
if [ "${cs_every}" -eq 1 ]; then
|
||||||
|
cs_every=""
|
||||||
|
else
|
||||||
|
cs_every="/${cs_every}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# generate valid random schedule values
|
||||||
|
# generally, "nighttime" and "weekend" will be preferred.
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028
|
||||||
|
rand_min=$(( RANDOM % 60 ))
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028
|
||||||
|
# rand_hour=$(( RANDOM % 24 ))
|
||||||
|
rand_hour=$(( (21 + RANDOM % 7) % 24 ))
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028
|
||||||
|
rand_day=$(( RANDOM % 31 + 1 ))
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028
|
||||||
|
# rand_weekday=$(( RANDOM % 7 ))
|
||||||
|
rand_weekday=$(( (6 + RANDOM % 2) % 7 ))
|
||||||
|
|
||||||
|
# shellcheck disable=SC3028
|
||||||
|
# rand_month=$(( RANDOM % 12 + 1 ))
|
||||||
|
rand_month=$(( RANDOM % 2 + 1 ))
|
||||||
|
|
||||||
|
case "${cs_units}" in
|
||||||
|
minute)
|
||||||
|
print_cron_schedule \
|
||||||
|
"*${cs_every}" "*" "*" "*" "*" "${cs_command}"
|
||||||
|
;;
|
||||||
|
hour)
|
||||||
|
print_cron_schedule \
|
||||||
|
"${rand_min}" "*${cs_every}" "*" "*" "*" "${cs_command}"
|
||||||
|
;;
|
||||||
|
day)
|
||||||
|
print_cron_schedule \
|
||||||
|
"${rand_min}" "${rand_hour}" "*${cs_every}" "*" "*" "${cs_command}"
|
||||||
|
;;
|
||||||
|
week)
|
||||||
|
print_cron_schedule \
|
||||||
|
"${rand_min}" "${rand_hour}" "*" "*" "${rand_weekday}" "${cs_command}"
|
||||||
|
;;
|
||||||
|
month)
|
||||||
|
print_cron_schedule \
|
||||||
|
"${rand_min}" "${rand_hour}" "${rand_day}" "*${cs_every}" "*" "${cs_command}"
|
||||||
|
;;
|
||||||
|
year)
|
||||||
|
print_cron_schedule \
|
||||||
|
"${rand_min}" "${rand_hour}" "${rand_day}" "${rand_month}" "*" "${cs_command}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_has_no_files () {
|
||||||
|
dhnf_directory="${1}"
|
||||||
|
|
||||||
|
# count files in directory
|
||||||
|
dhnf_filecount="$(
|
||||||
|
find "${dhnf_directory}" -type f -mindepth 1 -maxdepth 1 \
|
||||||
|
| wc -l
|
||||||
|
)"
|
||||||
|
|
||||||
|
# true if empty
|
||||||
|
test "${dhnf_filecount}" -eq "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
dir_to_unit () {
|
||||||
|
dtu_dirname="${1}"
|
||||||
|
|
||||||
|
case "${dtu_dirname}" in
|
||||||
|
minute|hour|day|week|month|year)
|
||||||
|
echo "${dtu_dirname}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
# truncated "daily"
|
||||||
|
dai)
|
||||||
|
echo "day"
|
||||||
|
;;
|
||||||
|
|
||||||
|
# truncated "annually"
|
||||||
|
annual)
|
||||||
|
echo "year"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
crontab_line '# crontab generated by kiwi-cron'
|
||||||
|
crontab_line '# generation time: '"$(date)"
|
||||||
|
crontab_line '#'
|
||||||
|
crontab_line "$(
|
||||||
|
print_cron_schedule \
|
||||||
|
"# min" "hour" "day" "month" "weekday" "command"
|
||||||
|
)"
|
||||||
|
|
||||||
|
# check *ly dirs in "/kiwi-cron" directory
|
||||||
|
schedule_dirs="$(
|
||||||
|
find "/kiwi-cron" -type d -name "*ly" -mindepth 1 -maxdepth 1
|
||||||
|
)"
|
||||||
|
|
||||||
|
for schedule_dir in ${schedule_dirs}; do
|
||||||
|
# ignore if no files
|
||||||
|
if dir_has_no_files "${schedule_dir}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# infer units by directory name
|
||||||
|
dir_name="${schedule_dir##*/}"
|
||||||
|
units="${dir_name%ly}"
|
||||||
|
units="$( dir_to_unit "${units}" )"
|
||||||
|
|
||||||
|
crontab_line "$(
|
||||||
|
create_schedule "1" "${units}" "run-parts '${schedule_dir}'"
|
||||||
|
)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# check dirs in "/kiwi-cron/every" directory
|
||||||
|
every_schedule_dirs="$(
|
||||||
|
find "/kiwi-cron/every" -type d -mindepth 1 -maxdepth 1
|
||||||
|
)"
|
||||||
|
|
||||||
|
for schedule_dir in ${every_schedule_dirs}; do
|
||||||
|
# ignore if no files
|
||||||
|
if dir_has_no_files "${schedule_dir}"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# infer schedule params by directory name
|
||||||
|
dir_name="${schedule_dir##*/}"
|
||||||
|
every="$( echo "${dir_name}" | awk -F_ '{print $1}' )"
|
||||||
|
units="$( echo "${dir_name}" | awk -F_ '{print $2}' )"
|
||||||
|
units="${units%s}"
|
||||||
|
|
||||||
|
crontab_line "$(
|
||||||
|
create_schedule "${every}" "${units}" "run-parts '${schedule_dir}'"
|
||||||
|
)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# replace crontab, run crond
|
||||||
|
echo "${crontab}" | crontab -
|
||||||
|
exec crond -fd 8
|
Loading…
Reference in a new issue