Skip to content

Instantly share code, notes, and snippets.

@mslinn
Last active September 27, 2023 10:35
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mslinn/23af96f609d2da0fcb9ecce2a48bef3a to your computer and use it in GitHub Desktop.
Save mslinn/23af96f609d2da0fcb9ecce2a48bef3a to your computer and use it in GitHub Desktop.
Run a cron job manually and immediately
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
X=Y
1 2 3 4 5 6 echo "Hello, world"
1 2 3 4 5 6 echo "Goodby, cruel world"
1 2 3 4 5 6 echo "Please spare me the drama"
#!/bin/bash
# Execute a user crontab entry with the proper environment
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
env -i bash --noprofile --norc -c "$DIR/cronTest2 $USER"
#!/bin/bash
# Prompt user for a user crontab entry to execute
function deleteTempFile {
rm -f $TEMP_FILE
}
function debug {
if [ "$DEBUG" ]; then >&2 printf "$1\n"; fi
}
function isValidLineNumber {
# $1 - number of lines
# $2 - requested line number
if [[ -n "${2//[0-9]+/}" ]] && (( $2 <= $1 )); then echo true; else echo false; fi
}
function isVariableAssignment {
[[ "$( echo "$1" | grep "=" )" ]]
}
function makeTempCrontab {
local -r ASTERISK=\\*
local -r NUMBER='[[:digit:]]{1,2}'
local -r NUMBERS="$NUMBER(,$NUMBER)+"
local -r CRON="^(($ASTERISK|$NUMBER|$NUMBERS)[[:space:]]+)"
local -r CRON5_REGEX="$CRON{5}"
local -r CRON6_REGEX="$CRON{6}"
rm -f "$TEMP_FILE"
local -r ALL_LINES="$( crontab -l )"
# Ignore empty lines and lines starting with # (comment lines)
local -r LINES="$(
echo "$ALL_LINES" | \
grep -v '^[[:space:]]*#' | \
grep -v '^[[:space:]]*$'
)"
if [[ -z "$LINES" ]]; then
echo "Your crontab is empty, nothing to do"
exit 1
fi
IFS=$'\n'
for LINE in $LINES; do
LINE="$( echo "$LINE" | sed 's/\s\+$//e' )" # remove trailing space
if [ "$( echo "$LINE" | grep "^$" )" ]; then
debug "" # ignore empty line
elif [ "$( echo "$LINE" | egrep "$CRON6_REGEX" )" ]; then
debug "6 field date/time specifier: $LINE"
# strip out when to run debug, leaving just the command to execute
echo "$LINE" | cut -f 7- -d ' ' >> "$TEMP_FILE"
elif [ "$( echo "$LINE" | egrep "$CRON5_REGEX" )" ]; then
debug "5 field date/time specifier: $LINE"
# strip out when to run debug, leaving just the command to execute
echo "$LINE" | cut -f 6- -d ' ' >> "$TEMP_FILE"
elif [ "$( echo "$LINE" | grep '^@' )" ]; then
debug "@declaration: $LINE"
# strip out @declaration, leaving just the command to execute
echo "$LINE" | cut -f 2- -d ' ' >> "$TEMP_FILE"
elif [ "$( echo "$LINE" | grep '=' )" ]; then
debug "Variable assignment: $LINE"
echo "$LINE" >> "$TEMP_FILE"
else
debug "Ignored: $LINE"
fi
done
unset IFS
}
function runUpToLine {
# Scans up to given line number in $TEMP_FILE
# Evaluates variable assignment
# Executes specified line
# Ignores remainder of file
# Function definitions are not supported
#
# $1 - line number to run
readarray CONTENTS < "$TEMP_FILE"
for (( i=0; i<=$1; i++ )); do
# >&2 echo "\$i=$i, \$1=$1, isVariableAssignment: $( isVariableAssignment $CONTENTS[$i] ), CONTENTS[$i]=${CONTENTS[$i]}"
if isVariableAssignment ${CONTENTS[$i]} || (( $i == $1 )); then
printf "\nEvaluating $(( i+1 )): ${CONTENTS[$i]}"
eval "${CONTENTS[$i]}"
fi
done
}
function selectLine {
>&2 echo "This is the crontab for $USER without comment lines or blank lines:"
cat -n "$TEMP_FILE" >&2
>&2 echo "Which line would you like to run as $USER now?"
local -r NUM_LINES=$( cat "$TEMP_FILE" | wc -l )
read LINE_NUMBER
# >&2 echo "NUM_LINES=$NUM_LINES, LINE_NUMBER=$LINE_NUMBER; valid: $( isValidLineNumber $NUM_LINES $LINE_NUMBER )"
while [[ $( isValidLineNumber $NUM_LINES $LINE_NUMBER ) == false ]]; do
>&2 echo "$LINE_NUMBER is not valid, please enter an integer from 1 to $NUM_LINES"
read LINE_NUMBER
# >&2 echo "NUM_LINES=$NUM_LINES, LINE_NUMBER=$LINE_NUMBER; valid: $( isValidLineNumber $NUM_LINES $LINE_NUMBER )"
done
(( LINE_NUMBER-- ))
echo ${LINE_NUMBER}
}
function doIt {
export USER=$1
local -r TEMP_FILE="$( mktemp crontabTest.XXX )"
trap deleteTempFile EXIT
makeTempCrontab
local -r LINE_NUMBER="$( selectLine )"
runUpToLine $LINE_NUMBER
}
doIt "$1"
$ cronTest
This is the crontab for without comment lines or blank lines:
1 X=Y
2 echo "Hello, world"
3 echo "Goodby, cruel world"
4 echo "Please spare me the drama"
Which line would you like to run as now?
55
55 is not valid, please enter an integer from 1 to 4
2
Evaluating 1: X=Y
Evaluating 2: echo "Hello, world"
Hello, world
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment