c0nspiracy
1/26/2014 - 3:18 PM

crontab script for Synology Diskstation

crontab script for Synology Diskstation

#!/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
#
SCRIPTNAME=`basename $0`

# 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=3
# Set to your editor of choice
EDITOR=nano

usage () {
  echo -e "Usage: $SCRIPTNAME [-l | -f | -e | -h]\n"
}

# Basic sanity checks.  Running as root.  One Parameter only.
[[ "`id -u`" =  "0" ]] || ( echo "Root only"; exit 1 )
[[ $# -ne 1 ]] && ( usage; exit 1 )

# Check for selected editor.  Default to vi
EDITOR=`/usr/bin/which $EDITOR`
[[ ! -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    "  -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"
  exit 0
}

check_new () {
  # Synocron is very picky. Check the file format

  ( # Start of output redirection block
    IFS="
"
    cat /etc/crontab | \
    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
  ) > $CHKCRON # end of output redirection block
  # Compare files and return the result
  diff /etc/crontab $CHKCRON >/dev/null 2>&1
  return $?
}

restart_cron () {
  echo "Refreshing cron daemon."
  /usr/syno/sbin/synoservice --restart crond
}

archive () { # Keep up to MAXVER versions
  ARCVER=$MAXVER
  while [[ $ARCVER -gt 1 ]]; do
    PRVVER=`expr $ARCVER - 1`
    mv -f $TMPNAME.$PRVVER $TMPNAME.$ARCVER
    ARCVER=$PRVVER
  done
  cp $TMPNAME ${TMPNAME}.1
}

edit_cron () {
  archive
  cp /etc/crontab ${TMPNAME}
  $EDITOR /etc/crontab
  diff /etc/crontab ${TMPNAME} >/dev/null 2>&1
  if [[ $? = 0 ]]; then
    echo "No changes made.  Doing nothing."
  else
    if check_new; then
      echo "Crontab altered."
      echo "Previous version saved in ${TMPNAME}"
      rm -f $CHKCRON
      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 $CHKCRON.  Restoring original version."
      cat /etc/crontab > $CHKCRON
      cat $TMPNAME > /etc/crontab
    fi
  fi
  exit 0
}

### Script flow ###################

while getopts lfhe flag; do
  case $flag in
  l) cat /etc/crontab; exit 0;;
  e) edit_cron;;
  f) restart_cron;;
  h) show_help;;
  ?) usage;;
  esac
done

## End of script flow #############