Pääsivulle

Timo Heikkinen / Opintojaksot / Älykkään sähkölaitteen projekti / Ohjelmien ajastettu suorittaminen /
Ohjelmien ajastettu suorittaminen

Usein on tarpeen suorittaa ohjelmia ennalta ajastettuna. Linux-ympäristössä tämä tapahtuu näppärästi cron-ajastuspalvelun avulla (cron [kreikan sanasta χρόνος, chronos] Raspberry.org-sivustolla, Wikipediassa). cron-palvelun ajastuksia hallitaan crontab-ohjelmalla.

Ohjelmia voidaan ajastaa myös mm. at-komennolla tai launchd-daemonilla. Tässä esimerkissä käytetään kuitenkin cron-palvelua sen yleiskäyttöisyyden takia.

Raspbianissa cron on oletusarvoisesti "päällä", joten palvelua ei tarvitse erikseen käynnistää.

Kokeillaan cronin toimintaa lisäämällä crontabiin kolme automaattista toiminnetta:

  1. Web-palvelimen käynnistäminen Raspberryn käynnistymisen yhteydessä
  2. Ledin sytyttäminen parillisilla minuuteilla
  3. Ledin sammuttaminen parittomilla minuuteilla

Omien ajastusten lisääminen tapahtuu crontab-ohjelmalla käyttämällä vipua -e: crontab -e. Ajastettuja ohjelmia voidaan suorittaa pääkäyttäjänä tai tavallisena käyttäjänä; riippuen ohjelman tarvitsemista käyttäjäoikeuksista, myös crontab käynnistetään joko pääkäyttäjänä tai tavallisena käyttäjänä.

Web-palvelimen käynnistäminen aina Raspberryn käynnistyessä

Web-palvelin tarvitsee pääkäyttäjän oikeuksia, joten crontab käynnistetään pääkäyttäjänä (sudo). Ohjelma kysyy, mitä editoria halutaan käyttää tiedoston muokkaamiseen 1. Oletuksena on nano - oletusarvo on kerrottu hakasuluissa 2. Jos oletusarvo kelpaa, riittää enter-painallus; muussa tapauksessa anna haluamasi vaihtoehdon numero ja paina enter:

pi@raspberrypi:~ $ sudo crontab -e
Select an editor.  To change later, run 'select-editor'. 1
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.tiny

Choose 1-3 [2]: 2

Valittu editori avautuu ja näyttää crontab-tiedostopohjan:

# 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

Lisätään tiedoston loppuun rivi, joka käynnistää web-palvelimen Raspberryn käynnistymisen yhteydessä:

@reboot python /home/pi/web-server/app.py

Ledin sytyttäminen ja sammuttaminen määräaikoina

Ledin sytyttäminen ja sammuttaminen voidaan (ja niin ollen pitää) tehdä tavallisen käyttäjän oikeuksilla. app.py-skripti ja main.html-sivupohja on luotu niin, että ledin ohjaaminen tapahtuu avaamalla selaimella sivu

http://<Raspberryn IP-osoite>/<GPIO-liittimen numero>/[on|off]

Koska tällä kertaa sekä selain että palvelin sijaitsevat samalla koneella, voidaan palvelimen IP-osoite korvata IP-protokollan määritysten mukaisesti localhost-nimellä tai kiinteällä IP-osoitteella 127.0.0.1. Tällöin, jos esimerkiksi halutaan GPIO-pinni 23 "päälle", kirjoitetaan selaimeen osoitteeksi

http://localhost/23/on

Jos selain olisi eri koneella kuin palvelin, voisi sivun osoite olla esimerkiksi

http://192.168.0.114/23/on
wget - web-latain

Oikean selaimen käyttäminen tätä tarkoitusta varten olisi turhan raskasta, koska minkään nettisivun sisältöä ei ole tarpeen näyttää kenellekään; led vain halutaan sytyttää ja sammuttaa. wget on ohjelma, jolla voidaan ladata web-sivuja tai muuta web-sisältöä komentoriviltä käsin ilman graafista käyttöliittymää, joten se soveltuu tähän tarkoitukseen erinomaisesti.

Käynnistä web-palvelin ja kokeile antaa pääteikkunassa seuraavat komennot - huomaa ensimmäisen rivin lopussa oleva &-merkki:

pi@raspberrypi:~ $ sudo python /home/pi/web-server/app.py & 1
[...] 2
wget -q http://localhost/23/on 3
[...] 4
wget -q http://localhost/23/off 5
[...] 6
fg 7
<ctrl>-c 8
pi@raspberrypi:~ $ 

1Käynnistetään web-palvelin taustalle
2Tulostuu web-palvelimen käynnistymistietoja
3Hae "hiljaisesti" (-q) sivu http://localhost/23/on ts. sytytä led
4Taustalla käyvä web-palvelin vastaanottaa sivupyynnön ja tulostaa sen tiedot
5Hae "hiljaisesti" (-q) sivu http://localhost/23/off ts. sammuta led
6Taustalla käyvä web-palvelin vastaanottaa sivupyynnön ja tulostaa sen tiedot
7Tuo web-palvelinohjelma taustalta "edustalle"
8Lopeta web-palvelinohjelman suorittaminen näppäämällä <ctrl>-c

wget + cron

Kun crontab -e käynnistetään tavallisena käyttäjänä ensimmäistä kertaa, ohjelma ilmoittaa, että käyttäjätunnuksella (tässä pi) ei vielä ole crontab-tiedostoa, joten se luo tyhjän tiedoston1. Ohjelma antaa myös tämän käyttäjän (eli pi:n) valita käytettävän editorin.

pi@raspberrypi:~ $ crontab -e
no crontab for pi - using an empty one 1

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.tiny

Choose 1-3 [2]:

Avautuu samanlainen "tyhjä" pohja kuin edellisellä kerralla, koska silloin tehdyt muutokset tallentuivat pääkäyttäjän crontab-tiedostoon, ja nyt käsitellään käyttäjän pi crontab-tiedostoa.

Jos ohjelmia halutaan suorittaa tiettyinä kellonaikana tai päivänä, suoritusaika määritellään seuraavanlaisilla riveillä:

*    *    *    *    *  suoritettava komento
+    +    +    +    +
|    |    |    |    |
|    |    |    |    +----- viikonpäivä (0 - 7) (0 tai 7 = sunnuntai)
|    |    |    +---------- kuukausi (1 - 12)
|    |    +--------------- päivä (1 - 31)
|    +-------------------- tunti (0 - 23)
+------------------------- minuutti (0 - 59)

Esimerkiksi jos haluttaisiin suorittaa komento check_mail joka päivä tasatunnein, lisättäisiin crontabiin rivi

0 * * * * check_mail

Tämä tarkoittaisi, että aina kun palvelimen kellon minuutti-kenttä saa arvon 0 ja tunti-, päivä-, kuukausi- ja viikonpäiväkenttä minkä tahansa arvon, suoritetaan ohjelma check_mail. Toisin sanottuna viikonpäivällä, kuukaudella, päivällä tai tunnilla ei ole merkitystä, koska niiden paikalla on ns. jokerimerkki, mutta minuuteilla on, koska sen paikalla on tietty numero. Koska kyseinen numero on nolla, suoritetaan check_mail aina, kun kello on 00:00, 01:00, 02:00 ja niin edelleen aina tasatunnein.

Ledi halutaan sytyttää parillisina minuutteina. Tämä on mahdollista, koska parittomuuden voi testata kentän arvolla */2.

Sammuttamisen pitää tapahtua parittomina minuutteina, minkä saa toteutettua kentän arvolla 1-59/2 (crontab man-sivu: Ranges can include "steps", so "1-9/2" is the same as "1,3,5,7,9".).

Lisää tiedoston loppuun rivit

*/2 * * * * wget -q --spider --server-response http://localhost/23/on > /dev/null 2>&1
1-59/2 * * * * wget -q --spider --server-response http://localhost/23/off > /dev/null 2>&1

Käynnistä Raspberry uudelleen, jolloin web-palvelin käynnistyy ja led saa sytytys- ja sammutuskäskyjä minuutin välein:

pi@raspberrypi:~ $ sudo shutdown -r now

Odota Raspberryn käynnistymistä ja testaa web-palvelimen toiminta menemällä web-selaimella osoitteeseen http://localhost/. Jos kaikki on kunnossa, näkyviin tulee GPIO-24:n ja 23:n tilan tulostava sivu. Kun sivua päivittää minuutin välein, pitäisi GPIO-23:n tila aina vaihtua.

Päivitetty 11.9.2017


© Timo Heikkinen | timo piste heikkinen at oamk piste fi