-
-
Save coderofsalvation/1102e56d3d4dcbb1e36f to your computer and use it in GitHub Desktop.
# portable cronjob wrapper to ensure : | |
# | |
# * only one process at the time (prevents process-overlap, handy for unique cron workers) | |
# * reverse cron's email behaviour (only emails on error) | |
# * ultraportable: only relies on flock, not on debians 'start-stop-daemon' or centos 'daemon' | |
# * nicelevel to tame cpu usage | |
# | |
# usage: cronjoblock <application> [args] | |
# example: cronjoblock /home/foo/myscript & | |
# cronjoblock /home/foo/myscript & <--- 'myscript' will only run when the previous run is finished | |
# | |
# there's is no output unless there are errors. This is handy in respect to cron's MAILTO variable: | |
# the stdout/stderr output will be suppressed (so cron will not send mails) *unless* the given process | |
# has an exitcode > 0 | |
# | |
[[ ! -n $1 ]] && { head -n11 $0 | sed 's/^#/ /g' | grep -v 'bin/bash'; exit; } | |
EXITCODE=0 | |
STDOUT="/tmp/.cronjoblock.$( echo "$*" | tr A-Z a-z | sed -e 's/[^a-zA-Z0-9\-]/-/g')" # logfilename containing cronjob args | |
LOCKFILE="$STDOUT.lock" | |
NICELEVEL=10 # don't overload cpu (higher is slower) | |
exec nice -n $NICELEVEL /usr/bin/flock -w 0 "$LOCKFILE" "$@" | tee -a "$STDOUT" # remove -a to flush log on each run | |
EXITCODE=$$; [[ ! $EXITCODE == 0 ]] && cat "$STDOUT" # output stdout to cron *only* on error | |
exit $EXITCODE # let cron know (trigger email) |
SHELL=/bin/bash | |
MAILTO="[email protected]" | |
# -------------- min (0 - 59) | |
# | --------------- hour (0 - 23) | |
# | | ---------------- day of month (1 - 31) | |
# | | | ----------------- month (1 - 12) | |
# | | | | ------------------ day of week (0 - 6) (0 to 6 are Sunday to Saturday, or use names; 7 is Sunday, the same as 0) | |
# | | | | | | |
# | | | | | | |
# * * * * * command to execute | |
*/5 * * * * cd /my/path && ./cronjoblock foo bar # run every 5 mins if not running | |
*/5 * * * * cd /my/path && ./cronjoblock foo bar &> /dev/null # run every 5 mins if not running (no output) |
Thanks for that script.
Can you please add more comments to your code. It is always hard to understand bash. I am not sure what happens here.
EDIT: What do you think of that?
#!/bin/bash
# Credits: https://gist.github.com/coderofsalvation/1102e56d3d4dcbb1e36f
# License: Unknown
# Author: Coder of Salvation / Leon van Kammen (https://gist.github.com/coderofsalvation)
# portable cronjob wrapper to ensure :
#
# * only one process at the time (prevents process-overlap, handy for unique cron workers)
# * reverse cron's email behaviour (only emails on error)
# * ultraportable: only reliest on flock, not on debians 'start-stop-daemon' or centos 'daemon'
# * nicelevel to tame cpu usage
#
# usage: cronjoblock <application> [args]
# example: cronjoblock /home/foo/myscript &
# cronjoblock /home/foo/myscript & <--- 'myscript' will only run when the previous run is finished
#
# there's is no output unless there are errors. This is handy in respect to cron's MAILTO variable:
# the stdout/stderr output will be suppressed (so cron will not send mails) *unless* the given process
# has an exitcode > 0
#
# If no arguments given just print the comment lines of that script and exit.
[[ ! -n $1 ]] && { head -n11 $0 | sed 's/^#/ /g' | grep -v 'bin\/bash'; exit; }
# Default exit code "success"
EXITCODE=0
# Create a sanitized version of all givin arguments
SANITIZED_ARGS=$( echo "$*" | tr A-Z a-z | sed -e 's/[^a-zA-Z0-9\-]/-/g')
STDOUT="/tmp/.cronjoblock.$SANITIZED_ARGS"
LOCKFILE="$STDOUT.lock"
# Execute
NICELEVEL=10
exec nice -n $NICELEVEL /usr/bin/flock --timeout 0 "$LOCKFILE" "$@" > "$STDOUT"
# output stdout to cron *only* on error
EXITCODE=$$; [[ ! $EXITCODE == 0 ]] && cat "$STDOUT"
# let cron know (trigger email)
exit $EXITCODE
Hi, thanks for making this script, I wanted to know if you could make a variation that only locks the cronjob to 1 process at the time (like the original), but still outputs everything to the console, so I can log everything into a file using the tee command, thanks!
done, I've added tee, so it'll always log to a file + stdout (and you can always tee afterwards) :D
(or add &>/dev/null
to supress stdout+stderr, see example)
Thanks for that script. Can you please add more comments to your code. It is always hard to understand bash. I am not sure what happens here.
done, I've annotated it.
Keep on cronning! ❤
Hi, thanks for making this script, I wanted to know if you could make a variation that only locks the cronjob to 1 process at the time (like the original), but still outputs everything to the console, so I can log everything into a file using the tee command, thanks!