Skip to content

Instantly share code, notes, and snippets.

@adamamyl
Forked from rcook/LICENSE
Last active August 29, 2015 14:16
Show Gist options
  • Save adamamyl/92cc98b64d41d93c2c86 to your computer and use it in GitHub Desktop.
Save adamamyl/92cc98b64d41d93c2c86 to your computer and use it in GitHub Desktop.
#!/bin/sh
#
# Provides missing crontab editing
# Note: Synology crond requires arguments separated by a TAB character
# and the crontab user field only supports root. These requirements are
# enforced by this script.
#
# John Kelly, 2013-05-03
# Richard Cook, 2014-02-21
#
SCRIPTPATH=$(readlink -f $0)
SCRIPTNAME=$(basename "$SCRIPTPATH")
# Default path to crontab file
CRONTABPATH=/etc/crontab
# Failed edits are kept in this file
CHKCRON=/etc/crontab.chk
# Previous version
TMPNAME=/etc/crontab.old
# Max versions to keep. One or greater
MAXVER=10
# Set to your editor of choice
EDITOR=${EDITOR}
usage() {
echo -e "Usage: $SCRIPTNAME [-l | -v | -f | -e | -h]\n"
}
# Check for selected editor. Default to vi
EDITOR=$(/usr/bin/which $EDITOR 2>&1)
[[ ! -x "$EDITOR" ]] && EDITOR=/bin/vi
show_help() {
echo -e 'Provides basic access to the crontab file'
echo -e 'with simple format checks\n'
usage
echo ' -l : Lists the current contents of the root crontab file'
echo ' -v : Verifies the current contents of the root crontab file'
echo ' -f : Refreshes the cron daemon'
echo ' -e : Edits the crontab file and refreshes the cron daemon if'
echo ' the file is actually changed; otherwise does nothing'
echo -e ' -h : Shows this help text\n'
}
verify_crontab() {
# Synocron is very picky. Check the file format
( # Start of output redirection block
IFS="
"
cat $1 | \
while read LINE; do
# Find out if empty or the first character is a #
echo "$LINE" | awk '{print $1}' | egrep "^#|^$" > /dev/null 2>&1
if [[ $? = 0 ]]; then
# Copy over comment/blank lines exactly
echo "$LINE"
else
unset IFS
# test convert using tabs to compare results
echo "$LINE" | while read MIN HO MD MO WD WH COM; do
echo -e "$MIN\t$HO\t$MD\t$MO\t$WD\troot\t$COM"
done
IFS="
"
fi
done
) > $2 # end of output redirection block
# Compare files and return the result
diff $1 $2 > /dev/null 2>&1
return $?
}
restart_cron() {
echo 'Refreshing cron daemon.'
SYNOSERVICE=/usr/syno/sbin/synoservicectl
if [ -f $SYNOSERVICE ]; then
$SYNOSERVICE --restart crond
return
fi
CRONDRC=/usr/syno/etc/rc.d/S04crond.sh
if [ -f $CRONDRC ]; then
$CRONDRC stop
$CRONDRC start
return
fi
echo 'Don'"'"'t know how to restart cron service.'
exit 1
}
archive_crontabs() { # Keep up to MAXVER versions
ARCVER=$MAXVER
while [[ $ARCVER -gt 1 ]]; do
PRVVER=$(expr $ARCVER - 1)
if [ -f $TMPNAME.$PRVVER ]; then
mv -f $TMPNAME.$PRVVER $TMPNAME.$ARCVER
fi
ARCVER=$PRVVER
done
cp $TMPNAME $TMPNAME.1
}
edit_crontab() {
archive_crontabs
cp $1 $TMPNAME
$EDITOR $1
diff $1 $TMPNAME > /dev/null 2>&1
if [[ $? = 0 ]]; then
echo "No changes made. Doing nothing."
else
if verify_crontab $1 $2; then
echo 'Crontab altered.'
echo "Previous version saved in $TMPNAME"
rm -f $2
restart_cron
else
echo 'Crontab file is NOT in the correct Synology format.'
echo 'Please use TABs between fields and specify root in sixth field.'
echo "Your version is saved in $2. Restoring original version."
diff $1 $2 | cat -A
cat $1 > $2
cat $TMPNAME > $1
fi
fi
exit 0
}
check_command() {
if [[ "$COMMAND" != '' ]]; then
echo -e 'You must specify exactly one command.\n'
usage
exit 1
fi
}
COMMAND=
while getopts p:lvfeh FLAG; do
case $FLAG in
p) CRONTABPATH=$(readlink -f $OPTARG);;
l) check_command; COMMAND=l;;
v) check_command; COMMAND=v;;
f) check_command; COMMAND=f;;
e) check_command; COMMAND=e;;
h) check_command; COMMAND=h;;
esac
done
if [[ "$COMMAND" = '' ]]; then
usage
exit 1
fi
case $COMMAND in
l)
echo "crontab at $CRONTABPATH"
cat $CRONTABPATH;;
v)
TEMPPATH=$(mktemp)
if verify_crontab $CRONTABPATH $TEMPPATH; then
echo "crontab at $CRONTABPATH is valid"
else
echo "crontab at $CRONTABPATH is not valid:"
diff $CRONTABPATH $TEMPPATH | cat -A
fi
rm $TEMPPATH;;
f) restart_cron;;
e) edit_crontab $CRONTABPATH $CHKCRON;;
h) show_help;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment