Tutorial: Scheduled tasks in CoreELEC

Tutorial: Using ‘cron’, ‘crontab’ and ‘sh’ in CoreELEC

I have seen some examples of implementation of tasks scheduled in kodi, libreelec and linux, but all are difficult to understand for a novice user in linux programming like myself. This has been written by a rookie for rookies.

I will give an example of scheduled tasks that I have implemented in my CoreELEC device:

1.- Check that ‘cron’ is activated in Settings->Services->Cron

2.- Open an SSH terminal and create the scripts directory with the commands:

(create directory in .config, this allows it to be saved in CoreELEC backups)
mkdir /storage/.config/scripts
(change attributes)
chmod 775 /storage/.config/scripts
(create a link in ‘storage’ to be able to access the new scripts directory from kodi)
ln -s /storage/.config/scripts /storage/scripts
(remember that from now /storage/.config/scripts is the same as /storage/scripts)

3.- The scheduled tasks will be in shell files in the scripts directory. Examples:

3.1.- File: /storage/scripts/load_epgguide

#!/bin/sh
#remove old guide
$(rm '/storage/.config/scripts/guide')
#load new zipped epg guide
$(wget -O '/storage/.config/scripts/guide.gz' 'http://xxx.xxx.xxx/xxx.gz')
#unzip epg guide
$(gzip -d -f '/storage/.config/scripts/guide.gz')

3.2.- File: /storage/scripts/update_duckdns

#!/bin/sh
#update dynamic dns for external access
$(curl 'https://xxx.xxx.xxx/update/<ddns_name>/<ddns_key>')

4.- All shell files in the ‘scripts’ directory will have execution permission. Examples:

chmod 755 /storage/scripts/load_epgguide
chmod 755 /storage/scripts/update_duckdns

5.- To execute any script we will use the sh command. Examples:

sh /storage/scripts/load_epgguide
sh /storage/scripts/update_duckdns

6.- To execute the scripts as scheduled tasks we will use the command:
crontab -e, and we will add lines as in the following example:

...
5 5 * * * sh /storage/.config/scripts/load_epgguide
10 5 * * * sh /storage/.config/scripts/update_duckdns
...

(load_epgguide will run every day at 5 and 5 in the morning, and update_duckdns will run at 5 and 10 in the morning)

This is all!

8 Likes

Thanks for your contribution and this really neat guide.

Why do you run shell commands with $()?

I am used to the Linux of the Asus router and there I have no problems with executing shell commands in scripts and I can run a script without the sh script call. I have seen that the CoreELEC shell is different and if I do not put the parentheses $ () some commands are executed with errors, CoreELEC also does not allow to execute the script without the sh command.

No need for $(). Show an example please where it doesn’t work

This does not work without $ ()

#!/bin/sh
wget -O ‘/storage/.config/scripts/guide.gz’ ‘http://epg.tododream.com/latinmunich_xmltv-movistar-spain_todo.gz

Of course this works without $().

CoreELEC:~ # vi test.sh
CoreELEC:~ # chmod +x test.sh 
CoreELEC:~ # ./test.sh 
Connecting to epg.tododream.com (78.47.83.207:80)
wget: can't open '/storage/.config/scripts/guide.gz': No such file or directory
CoreELEC:~ # mkdir .config/scripts
CoreELEC:~ # ./test.sh 
Connecting to epg.tododream.com (78.47.83.207:80)
guide.gz             100% |*********************************************************************************************************************************************************************| 2452k  0:00:00 ETA
CoreELEC:~ # cat test.sh 
#!/bin/sh
wget -O /storage/.config/scripts/guide.gz http://epg.tododream.com/latinmunich_xmltv-movistar-spain_todo.gz
CoreELEC:~ # ./test.sh 
Connecting to epg.tododream.com (78.47.83.207:80)
guide.gz             100% |*********************************************************************************************************************************************************************| 2452k  0:00:00 ETA

The error, whenever I executed the script without $ () was

CoreELEC: ~ / .config / scripts # sh load_epgguide2
Connecting to epg.tododream.com (78.47.83.207:80)
wget: server returned error: HTTP / 1.1 400 Bad Request

With $ () it always worked well. I do not know how to give an explanation.

CoreELEC:~ # sh test.sh 
Connecting to epg.tododream.com (78.47.83.207:80)
guide.gz             100% |*********************************************************************************************************************************************************************| 2452k  0:00:00 ETA

Please give me the output of:
ls -l /storage/.config/scripts

and also

which sh

CoreELEC:~/.config/scripts # ls -l
total 31744
-rw-r--r--    1 root     root      32501803 Mar 15 12:43 guide
-rwxr-xr-x    1 root     root           218 Mar 15 01:48 load_epgguide
-rwxr-xr-x    1 root     root           113 Mar 15 00:29 restart_xti_3442
-rwxr-xr-x    1 root     root           106 Mar 15 09:33 update_duckdns
CoreELEC:~/.config/scripts #

looks fine. Now the command:

which sh

CoreELEC:~/.config/scripts # sh --help
BusyBox v1.29.3 (2019-02-27 00:03:50 GMT) multi-call binary.

Usage: sh [-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]

Unix shell interpreter
CoreELEC:~/.config/scripts #

But where is it?
you calling sh directly and not ./script

my sh is in /usr/bin/sh

I do not know where sh is, I just write sh and I hope the system executes it :rofl::rofl::rofl:

Sorry I said you can check it with the following command:
which sh

CoreELEC:~/.config/scripts # which sh
/usr/bin/sh
CoreELEC:~/.config/scripts #

Well something is weird in your setup because it works with fresh installed CE.

Can you give me the output of:

env
CoreELEC:~/.config/scripts # env
USER=root
MAIL=/var/mail/root
SSH_CLIENT=192.168.168.6 6866 22
HOSTNAME=CoreELEC
SHLVL=2
LD_LIBRARY_PATH=/usr/lib:/storage/.kodi/addons/plugin.video.SportsDevil/lib:/storage/.kodi/addons/plugin.video.alfa/lib:/storage/.kodi/addons/script.exodusredux.artwork/lib:/storage/.kodi/addons/script.exodusredux.metadata/lib:/storage/.kodi/addons/script.module.addon.common/lib:/storage/.kodi/addons/script.module.addon.signals/lib:/storage/.kodi/addons/script.module.arrow/lib:/storage/.kodi/addons/script.module.autocompletion/lib:/storage/.kodi/addons/script.module.beautifulsoup/lib:/storage/.kodi/addons/script.module.beautifulsoup4/lib:/storage/.kodi/addons/script.module.certifi/lib:/storage/.kodi/addons/script.module.chardet/lib:/storage/.kodi/addons/script.module.cherrypy/lib:/storage/.kodi/addons/script.module.commoncore/lib:/storage/.kodi/addons/script.module.dateutil/lib:/storage/.kodi/addons/script.module.exodusredux/lib:/storage/.kodi/addons/script.module.feedparser/lib:/storage/.kodi/addons/script.module.futures/lib:/storage/.kodi/addons/script.module.garepobg/lib:/storage/.kodi/addons/script.module.httplib2/lib:/storage/.kodi/addons/script.module.idna/lib:/storage/.kodi/addons/script.module.inputstreamhelper/lib:/storage/.kodi/addons/script.module.kodi65/lib:/storage/.kodi/addons/script.module.kodibgcommon/lib:/storage/.kodi/addons/script.module.liveresolver/lib:/storage/.kodi/addons/script.module.livestreamer/lib:/storage/.kodi/addons/script.module.metadatautils/lib:/storage/.kodi/addons/script.module.metahandler/lib:/storage/.kodi/addons/script.module.musicbrainz/lib:/storage/.kodi/addons/script.module.myconnpy/lib:/storage/.kodi/addons/script.module.openscrapers/lib:/storage/.kodi/addons/script.module.parsedom/lib:/storage/.kodi/addons/script.module.python.koding.aio/lib:/storage/.kodi/addons/script.module.requests/lib:/storage/.kodi/addons/script.module.resolveurl/lib:/storage/.kodi/addons/script.module.routing/lib:/storage/.kodi/addons/script.module.simple.downloader/lib:/storage/.kodi/addons/script.module.simplecache/lib:/storage/.kodi/addons/script.module.simplejson/lib:/storage/.kodi/addons/script.module.singledispatch/lib:/storage/.kodi/addons/script.module.six/lib:/storage/.kodi/addons/script.module.slproxy/lib:/storage/.kodi/addons/script.module.streamlink.crypto/lib:/storage/.kodi/addons/script.module.thetvdb/lib:/storage/.kodi/addons/script.module.unidecode/lib:/storage/.kodi/addons/script.module.universalscrapers/lib:/storage/.kodi/addons/script.module.urllib3/lib:/storage/.kodi/addons/script.module.urlresolver/lib:/storage/.kodi/addons/script.module.xmltodict/lib:/storage/.kodi/addons/script.module.youtube.dl/lib:/storage/.kodi/addons/script.tvaddons.debug.log/lib:/storage/.kodi/addons/script.video.F4mProxy/lib:/storage/.kodi/addons/service.tvheadend42/lib:/storage/.kodi/addons/service.xbmc.versioncheck/lib:/usr/lib/pulseaudio
HOME=/storage
OLDPWD=/storage
SSH_TTY=/dev/pts/0
PS1=\[\e[1;32m\]\h\[\e[1;32m\]:\[\e[1;34m\]\w \[\e[0m\]\$
LOGNAME=root
TERM=xterm
PATH=/usr/bin:/usr/sbin:/storage/.kodi/addons/service.softcam.oscam/bin:/storage/.kodi/addons/service.tvheadend42/bin
SYSTEMD_COLORS=0
SHELL=/bin/sh
PWD=/storage/scripts
SSH_CONNECTION=192.168.168.6 6866 192.168.168.16 22
EDITOR=nano
CoreELEC:~/.config/scripts #