crontab script

Any questions about the Command Line Interface can be placed here!
Forum rules
We've moved! Head over to Synology Community (community.synology.com) to meet up with our team and other Synology enthusiasts!
User avatar
johnk.dev.null
Versed
Versed
Posts: 274
Joined: Tue Apr 02, 2013 8:00 pm
Location: UK

crontab script

Unread post by johnk.dev.null » Sat May 04, 2013 12:02 am

I've been working on a script to give the missing crontab functionality. It provides the following -

crontab -l = list the /etc/crontab
crontab -c = checks current crontab for required Synology format
crontab -e = edit crontab and restart if accepted
crontab -f = reload cron daemon without changing anything.
crontab -h = show help information.

Synology cron is very fussy. The fields need to be separated by TABs otherwise they will be removed on next boot. The cron entry can only be a root job, so the sixth field must be root otherwise that line will be deleted on reboot, so ...

The script does some simple tests to confirm that the fields are separated with TABs and the sixth field is root. If acceptable the old version is saved as /etc/crontab.old. Otherwise the failed version is saved as /etc/crontab.chk. If it is acceptable then crond is restarted to activate the new file.

There are a couple of user settings in the script.
MAXVER determines how many old versions are saved. Default = 2.
EDITOR determines the editor to use. Default = vi.

To save the script and make it available, copy the contents into your clipboard then in a root SSH session, run the command
vi /usr/local/sbin/crontab
press 'i', paste in the script contents and save it (press Esc then :wq! ). Then set the permissions
chmod 755 /usr/local/sbin/crontab.

Updated to use the current Synology restart method - 11th July 2015.
Updated to cope with MAILTO= and PATH= lines - 17th Nov. 2016.

Code: Select all

#!/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
#
# Amendment history
# JK 2014-01-01.  Added a crontab check/convert option.
# JK 2014-01-03.  Now ignores trailing spaces.
# JK 2014-03-08.  Now ignores multiple consecutive tabs
# JK 2014-03-12.  Now used killall -HUP to refresh crond.
# JK 2015-07-11.  Now uses /usr/syno/sbin/synoservicectl to refresh cron
#                 Added a file format check/conversion using awk.
# JK 2016-11-17.  Updated to cope with PATH= and MAILTO= lines
#
SCRIPTNAME=`basename $0`

# Failed edits or conversions are kept in this file
CHKCRON=/etc/crontab.chk
# Previous version
TMPNAME=/etc/crontab.old
# Max versions to keep.  One or greater
MAXVER=2
# Set to your editor of choice
EDITOR=vi

usage () {
  echo -e "Usage: $SCRIPTNAME [-c | -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    "  -c : Checks current root crontab file for Synology format."
  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
}

convert_cron () {
  if check_new; then
    echo "No content changes required"
    rm -f $CHKCRON
  else
    echo "Your crontab file is NOT in the correct Synology format."
    echo "Please use TABs between fields and specify root in sixth field."
    echo "Your converted version is saved in $CHKCRON."
    echo "Please confirm differences using 'diff /etc/crontab $CHKCRON' before use."
  fi
}

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 "^#|^$|^[a-zA-Z0-9_]+=" >/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
        # add x to line and remove it later to retain trailing spaces
        # to ensure a correct comparison.
        echo "${LINE}x" | while read MIN HO MD MO WD WH COM; do
          COM=`echo "$COM" | sed 's/x$//'`
          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
  /usr/bin/tr -s '\t' '\t' < /etc/crontab >/etc/crontab.test
  /usr/bin/tr -s '\t' '\t' < $CHKCRON > ${CHKCRON}.test
  diff /etc/crontab.test ${CHKCRON}.test >/dev/null 2>&1
  RET=$?
  rm -f /etc/crontab.test ${CHKCRON}.test
  return $RET
}

restart_cron () {
  echo "Refreshing cron daemon."
  /usr/syno/sbin/synoservicectl --reload 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
}

fformat_cron () {
  TMPCRON=/tmp/crontab$$
  CRONSIZE=`ls -l /etc/crontab | awk '{print $5}'`
  awk '{ sub("\r$", ""); print }' /etc/crontab > $TMPCRON
  NEWSIZE=`ls -l $TMPCRON | awk '{print $5}'`
  if [ $CRONSIZE -eq $NEWSIZE ]; then
    echo "Crontab file is in Linux file format.  No conversion necessary"
  else
    echo "Crontab file is in Windows file format.  Converting"
    cat $TMPCRON > /etc/crontab
  fi  
  rm -f $TMPCRON
}


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

while getopts clfhe flag; do
  case $flag in
  c) fformat_cron;
     convert_cron;;
  l) cat /etc/crontab;;
  e) edit_cron;;
  f) restart_cron;;
  h) show_help;;
  ?) usage;;
  esac
done

## End of script flow #############
Last edited by johnk.dev.null on Thu Nov 17, 2016 6:42 pm, edited 5 times in total.
DSM 6.1.5-15254 Update 1

pz1
Knowledgeable
Knowledgeable
Posts: 374
Joined: Fri Oct 19, 2007 9:56 am
Location: Netherlands

Re: crontab script

Unread post by pz1 » Sat Jun 01, 2013 10:41 pm

Nice tool. Ran it on my crontab table, and it saved OK. Unfortunately it is still not working.

My crontab looks like

Code: Select all

#minute>hour<-->mday<-->month<->wday<-->who<--->command
17<---->5<----->*<----->*<----->1,4<--->root<-->/usr/syno/bin/synopkg chkupgradepkg
0<----->0<----->*<----->*<----->*<----->root<-->/usr/sbin/ntpdate -b ntp.xs4all.nl
42<---->21<---->*<----->*<----->2,5<--->root<-->/usr/bin/php -n -d safe_mode_exec_dir='' /usr/syno/bin/autoupdate.php
8<----->0<----->*<----->*<----->0<----->root<-->/var/packages/AntiVirus/target/bin/synoavscan --all
10<---->*<----->*<----->*<----->*<----->root<-->/volume1/@appstore/OpenRemote/webapps/private/weatherlogger.sh
It is the last entry that does not seem to run. The originale script is cut down to this, and still does not work:

Code: Select all

#!/bin/sh
cd /volume1/@appstore/OpenRemote/webapps/private
date -u >> test.logger
exit
If started manually, the script runs fine, and does add a timestamp to the test.logger file. From crontab nothing happens. It's obvious something silly, but I don't see it.
DS-207+ 128MB; DSM 3.1-1594
HDD: WDC WD10EADS-00L5B1 (01.01A01)
LMS 7.7.1 via SSODS4.9.1mod2 (by j-r)
DS212+ 512MB; DSM 4.3-3827 Update 7
LMS 7.7.2-007 via Synology spk

User avatar
maxxfi
Compiler
Compiler
Posts: 6794
Joined: Sun Dec 27, 2009 12:13 pm
Location: Espoo, Finland

Re: crontab script

Unread post by maxxfi » Sun Jun 02, 2013 6:37 am

Assuming that the crontab format is correct (e.g. all fields spaced by tab), I can suggest to add some 'debug' to the crontab line, like:
"10 * * * * root /volume1/@appstore/OpenRemote/webapps/private/weatherlogger.sh >>/tmp/wl.debug 2>&1"
Update crond (stop and restart the crond deamon) and wait that the the entry is triggered.
Then go to read the /tmp/wl.debug file and see if there is any error while executing the command.
If the file does not exist, it is a sign that the crontab entry has not been read at all.
No longer using Synology NAS, moved to more open source solutions.
DS-106j > DS-210j > DS-411

pz1
Knowledgeable
Knowledgeable
Posts: 374
Joined: Fri Oct 19, 2007 9:56 am
Location: Netherlands

Re: crontab script

Unread post by pz1 » Sun Jun 02, 2013 7:41 am

Thank you for replying.
maxxfi wrote:Assuming that the crontab format is correct (e.g. all fields spaced by tab), I can suggest to add some 'debug' to the crontab line, like:
"10 * * * * root /volume1/@appstore/OpenRemote/webapps/private/weatherlogger.sh >>/tmp/wl.debug 2>&1"
Update crond (stop and restart the crond deamon) and wait that the the entry is triggered.
Then go to read the /tmp/wl.debug file and see if there is any error while executing the command.
If the file does not exist, it is a sign that the crontab entry has not been read at all.
If I follow your recipe the debug file does not appear.
I do get an empty wl.debug file if I (logged in as root) manually give the command:

Code: Select all

/volume1/@appstore/OpenRemote/webapps/private/weatherlogger.sh >>/tmp/wl.debug 2>&1
By the way, what does the 2>&1 do? (I have very little Linux knowledge)
DS-207+ 128MB; DSM 3.1-1594
HDD: WDC WD10EADS-00L5B1 (01.01A01)
LMS 7.7.1 via SSODS4.9.1mod2 (by j-r)
DS212+ 512MB; DSM 4.3-3827 Update 7
LMS 7.7.2-007 via Synology spk

User avatar
maxxfi
Compiler
Compiler
Posts: 6794
Joined: Sun Dec 27, 2009 12:13 pm
Location: Espoo, Finland

Re: crontab script

Unread post by maxxfi » Sun Jun 02, 2013 8:47 am

If the file did not appear at all, then I think it has not been executed.
Perhaps there is a mistake with the syntax, e.g. some field is not separated by tab but by spaces.
You can use "cat -A /etc/crontab" to check 'invisible' characters.

The "2>&1" means 'redirect standard error to standard output'.
So ">>/tmp/wl.debug 2>&1" means: If the script has to output something (e.g. from a 'echo' command), write it to the /tmp/wl.debug file (appending to it, do not wipe old content) . If the script syntax is wrong or some command in the script fails to run, write the error message to the same place as regular output (i.e. the file /tmp/wl.debug).
No longer using Synology NAS, moved to more open source solutions.
DS-106j > DS-210j > DS-411

pz1
Knowledgeable
Knowledgeable
Posts: 374
Joined: Fri Oct 19, 2007 9:56 am
Location: Netherlands

Re: crontab script

Unread post by pz1 » Sun Jun 02, 2013 10:43 am

maxxfi wrote: You can use "cat -A /etc/crontab" to check 'invisible' characters.

Code: Select all

#minute^Ihour^Imday^Imonth^Iwday^Iwho^Icommand$
17^I5^I*^I*^I1,4^Iroot^I/usr/syno/bin/synopkg chkupgradepkg$
0^I0^I*^I*^I*^Iroot^I/usr/sbin/ntpdate -b ntp.xs4all.nl $
42^I21^I*^I*^I2,5^Iroot^I/usr/bin/php -n -d safe_mode_exec_dir='' /usr/syno/bin/autoupdate.php$
8^I0^I*^I*^I0^Iroot^I/var/packages/AntiVirus/target/bin/synoavscan --all$
10^I*^I*^I*^I*^Iroot^I/volume1/@appstore/OpenRemote/webapps/private/weatherlogger.sh >> /tmp/wl.debug 2>&1
If I look with the Hex view in Midnight Commander, the ^I signs are represented as 09. So that seems OK
DS-207+ 128MB; DSM 3.1-1594
HDD: WDC WD10EADS-00L5B1 (01.01A01)
LMS 7.7.1 via SSODS4.9.1mod2 (by j-r)
DS212+ 512MB; DSM 4.3-3827 Update 7
LMS 7.7.2-007 via Synology spk

User avatar
maxxfi
Compiler
Compiler
Posts: 6794
Joined: Sun Dec 27, 2009 12:13 pm
Location: Espoo, Finland

Re: crontab script

Unread post by maxxfi » Sun Jun 02, 2013 12:26 pm

Hmm... in those situation I can only suggest to try to rewrite the line, so:
- remove the last line
- stop and restart cron to accept the updated crontab
- rewrite the line (possibly editing manually, without using copy & paste)
- stop and restart cron again
No longer using Synology NAS, moved to more open source solutions.
DS-106j > DS-210j > DS-411

pz1
Knowledgeable
Knowledgeable
Posts: 374
Joined: Fri Oct 19, 2007 9:56 am
Location: Netherlands

Re: crontab script

Unread post by pz1 » Sun Jun 02, 2013 2:08 pm

maxxfi wrote:Hmm... in those situation I can only suggest to try to rewrite the line, so:
- remove the last line
- stop and restart cron to accept the updated crontab
- rewrite the line (possibly editing manually, without using copy & paste)
- stop and restart cron again
I did all this already a couple of times (including typing character by character) before posting to the forum.
I'll see if it works if I create a completely new file.

Anyhow thank you for spending so much time on this. I really appreciate.
Pieter
DS-207+ 128MB; DSM 3.1-1594
HDD: WDC WD10EADS-00L5B1 (01.01A01)
LMS 7.7.1 via SSODS4.9.1mod2 (by j-r)
DS212+ 512MB; DSM 4.3-3827 Update 7
LMS 7.7.2-007 via Synology spk

pz1
Knowledgeable
Knowledgeable
Posts: 374
Joined: Fri Oct 19, 2007 9:56 am
Location: Netherlands

Re: crontab script

Unread post by pz1 » Mon Jun 03, 2013 11:04 am

pz1 wrote: I'll see if it works if I create a completely new file.
This finally did the trick :D
DS-207+ 128MB; DSM 3.1-1594
HDD: WDC WD10EADS-00L5B1 (01.01A01)
LMS 7.7.1 via SSODS4.9.1mod2 (by j-r)
DS212+ 512MB; DSM 4.3-3827 Update 7
LMS 7.7.2-007 via Synology spk

wcndave
Experienced
Experienced
Posts: 120
Joined: Fri Dec 19, 2008 12:36 am

Re: crontab script

Unread post by wcndave » Wed Dec 18, 2013 11:19 am

I installed this and saved a change, which results in

Crontab file is NOT in the correct Synology format.
Please use TABs between fields and specify root in sixth field.
Your version is saved in /etc/crontab.chk. Restoring original version.

I tried everything, and finally resorted to a non-change change.

I made one of the cron jobs called with a different scriptname, just added 2 to the end, and I got this error.

So it seems the checking is not working?

For reference, here is my cron, however this is the same as the current working version before I installed your modification.

Code: Select all

#minute hour    mday    month   wday    who     command

0       *       *       *       *       root    /volume1/video/convert.sh
8       0       *       *       *       root    /volume1/video/mm_sync.sh

53      0       *       *       1,4     root    /usr/syno/bin/synopkg chkupgradepkg
30      0       *       *       *       root    /usr/syno/bin/syno_poweroff_feasible_check
0       9       *       *       2,3,4,5 root    /usr/syno/bin/syno_poweroff_feasible_check
DS712+: 2xWD20EACS (2TB) running in RAID 1
DS409+ 4xWD60EADS (24TB) running in Basic

Dune HD

User avatar
johnk.dev.null
Versed
Versed
Posts: 274
Joined: Tue Apr 02, 2013 8:00 pm
Location: UK

Re: crontab script

Unread post by johnk.dev.null » Wed Jan 01, 2014 10:07 pm

Hi wcndave,

Sorry you're having problems with it. It seems to be working for me. It might be a number of things but initially it sounds to me like you already have some spaces in your crontab instead of tab characters.
Spaces in your crontab will NOT prevent it from running correctly, it just means that those lines will not survive a reboot as Synology filters out lines that don't satisfy their checks and so the script also refuses them.

I'm afraid the listing of your crontab is of no use for diagnosing the issue since this forum does not preserve tabs in quoted code so I can't tell if your crontab is indeed in an incorrect format.

Please run the following command and paste in the resulting text -

catv -t /etc/crontab

On my NAS this displays tab characters as ^I. E.g. -

Code: Select all

#minute^Ihour^Imday^Imonth^Iwday^Iwho^Icommand
25^I5^I*^I*^I3,6^Iroot^I/usr/syno/bin/synopkg chkupgradepkg
7^I4^I*^I*^I0^Iroot^I/tmp/synoschedtask --run id=1
3^I2^I*^I*^I*^Iroot^I/tmp/synoschedtask --run id=2
11^I1^I*^I*^I6^Iroot^I/tmp/synoschedtask --run id=5
DSM 6.1.5-15254 Update 1

User avatar
johnk.dev.null
Versed
Versed
Posts: 274
Joined: Tue Apr 02, 2013 8:00 pm
Location: UK

Re: crontab script

Unread post by johnk.dev.null » Thu Jan 02, 2014 12:02 am

The updated script has a new option to check the existing crontab. E.g. Where the crontab file is ok -

Code: Select all

crontab -c
No changes required
or the crontab file has problems -

Code: Select all

crontab -c
Crontab file is NOT in the correct Synology format.
Please use TABs between fields and specify root in sixth field.
Your converted version is saved in /etc/crontab.chk.
Please confirm differences using 'diff /etc/crontab /etc/crontab.chk' before use.
Updated script version: 11th July 2015.

Code: Select all

Script updated in first post of thread.
When run it will produce a converted version where necessary in /etc/crontab.chk. You should check it and if it looks ok then you could move it into place using

cat /etc/crontab.chk > /etc/crontab
crontab -f
Last edited by johnk.dev.null on Sat Jul 11, 2015 5:09 pm, edited 2 times in total.
DSM 6.1.5-15254 Update 1

wcndave
Experienced
Experienced
Posts: 120
Joined: Fri Dec 19, 2008 12:36 am

Re: crontab script

Unread post by wcndave » Thu Jan 02, 2014 11:11 pm

mine seems to have no spaces.

Code: Select all

DMNAS0> catv -t /etc/crontab
#minute^Ihour^Imday^Imonth^Iwday^Iwho^Icommand

0^I*^I*^I*^I*^Iroot^I/volume1/video/convert.sh
8^I0^I*^I*^I*^Iroot^I/volume1/video/mm_sync.sh

53^I0^I*^I*^I1,4^Iroot^I/usr/syno/bin/synopkg chkupgradepkg
I tried your new script, then did a diff, and could still see no difference.

Code: Select all

DMNAS0> crontab -c
Crontab file is NOT in the correct Synology format.
Please use TABs between fields and specify root in sixth field.
Your converted version is saved in /etc/crontab.chk.
Please confirm differences using 'diff /etc/crontab /etc/crontab.chk' before use.
DMNAS0> diff /etc/crontab /etc/crontab.chk
--- /etc/crontab
+++ /etc/crontab.chk
@@ -1,6 +1,6 @@
 #minute        hour    mday    month   wday    who     command

 0      *       *       *       *       root    /volume1/video/convert.sh
-8      0       *       *       *       root    /volume1/video/mm_sync.sh
+8      0       *       *       *       root    /volume1/video/mm_sync.sh

 53     0       *       *       1,4     root    /usr/syno/bin/synopkg chkupgradepkg
DMNAS0> catv -t /etc/crontab
#minute^Ihour^Imday^Imonth^Iwday^Iwho^Icommand

0^I*^I*^I*^I*^Iroot^I/volume1/video/convert.sh
8^I0^I*^I*^I*^Iroot^I/volume1/video/mm_sync.sh

53^I0^I*^I*^I1,4^Iroot^I/usr/syno/bin/synopkg chkupgradepkg

DMNAS0> catv -t /etc/crontab.chk
#minute^Ihour^Imday^Imonth^Iwday^Iwho^Icommand

0^I*^I*^I*^I*^Iroot^I/volume1/video/convert.sh
8^I0^I*^I*^I*^Iroot^I/volume1/video/mm_sync.sh

53^I0^I*^I*^I1,4^Iroot^I/usr/syno/bin/synopkg chkupgradepkg
DMNAS0>
Then I copied the file over, and it seems ok, so it works, thanks again!
DS712+: 2xWD20EACS (2TB) running in RAID 1
DS409+ 4xWD60EADS (24TB) running in Basic

Dune HD

User avatar
johnk.dev.null
Versed
Versed
Posts: 274
Joined: Tue Apr 02, 2013 8:00 pm
Location: UK

Re: crontab script

Unread post by johnk.dev.null » Thu Jan 02, 2014 11:51 pm

Ok glad it's now working.

It was some kind of difference on the mm_sync.sh line. Could have been a stray space character at the end of the line that confused the admittedly simplistic checks.

I should have asked you to run 'catv -et /etc/crontab' instead. That would have shown spaces at the end of the line.

New version now ignores trailing spaces AND multiple tabs when comparing. (Updated 8th March 2014)

Code: Select all


Updated version is in first post of thread.


Regards

JohnK
Last edited by johnk.dev.null on Sat Jul 11, 2015 5:10 pm, edited 2 times in total.
DSM 6.1.5-15254 Update 1

wcndave
Experienced
Experienced
Posts: 120
Joined: Fri Dec 19, 2008 12:36 am

Re: crontab script

Unread post by wcndave » Fri Jan 03, 2014 1:14 pm

Thanks. I did check for trailing spaces when editing it. I saw in the diff which line it was, and could not fathom it.

I also did a replace all spaces, and still no go.

anyway, it works now, and it's really great to have the standard crontab commands available, so thanks once again!

Dave
DS712+: 2xWD20EACS (2TB) running in RAID 1
DS409+ 4xWD60EADS (24TB) running in Basic

Dune HD

Locked

Return to “Command Line Interface”