Difference between revisions of "Cron"
Line 10: | Line 10: | ||
|CODE=[https://github.com/ethersex/ethersex/tree/master/services/cron https://github.com/ethersex/ethersex/tree/master/services/cron] | |CODE=[https://github.com/ethersex/ethersex/tree/master/services/cron https://github.com/ethersex/ethersex/tree/master/services/cron] | ||
}} | }} | ||
+ | |||
+ | Cron daemon manage cron jobs. This rules define repeated or unique events that call certain commands. | ||
+ | |||
+ | Cron jobs are implemented in two flavors: a static list that is defined at compile time and not changeable | ||
+ | at runtime, and a dynamic approach, which loads the joblist to the RAM at statup. Jobs can be added and | ||
+ | removed at runtime. | ||
+ | |||
+ | == Preconditions == | ||
+ | Beide Ansätze haben gemeinsam, dass du erst einmal eine Funktion definieren musst, welche vom Cron daemon zum | ||
+ | bestimmten Zeitpunkt aufgerufen werden kann. Die Funktionssignatur sieht allerdings, abhängig davon welche | ||
+ | Implementierung du wählst, leicht anders aus. | ||
+ | |||
+ | == Menuconfig == | ||
+ | Das Modul benötigt allerdings die aktuelle Zeit um richtig funktionieren zu können. Du musst daher im selben | ||
+ | Untermenü mindestens eine Zeitquelle ebenfalls einschalten. | ||
+ | Um Crontabs in ethersex zu aktivieren, wählt man im Menü | ||
+ | |||
+ | │ │ Load a Default Configuration ---> | ||
+ | │ │ ... | ||
+ | │ │ Applications ---> | ||
+ | │ │ ... | ||
+ | │ │ [*] Cron daemon ---> | ||
+ | │ │ [ ] Cron daemon (static jobs) | ||
+ | |||
+ | == Static Cron Daemon == | ||
+ | Die Funktion, welche der Daemon aufrufen soll, muss folgende Signatur haben '''void func(void)''' | ||
+ | und muss direkt in cron_static/cron_static.c definiert werden. | ||
+ | |||
+ | Es muss dann nur noch eine Regel in die Array Struktur events vom Typ ''cron_static_event_t'' eingefügt werden. | ||
+ | Die Werte der Reihenfolge nach stehen für Minute, Stunde, Tag, Monat, Wochentag, Callback Funktion und ob UTC | ||
+ | oder die lokale Zeitzone benutzt werden soll. | ||
+ | |||
+ | Eine -1 steht für einen Platzhalter. Da die Einträge ca. jede Minute | ||
+ | einmal geprüft werden, wird also ein Eintrag mit nur Platzhalter Werten auch ca. jede Minute ausgeführt. | ||
+ | |||
+ | Werte unter -1 haben die Bedeutung von "jede x-te Minute/Stunde/etc". Also ein Wert von -4 | ||
+ | an der Minutenstelle bedeutet, dass der Crontab jede 4te Minute ausgeführt wird. | ||
+ | |||
+ | == Dynamic Cron Daemon == | ||
+ | === View jobs via ecmd === | ||
+ | Einfach den ecmd Befehl '''cron list''' zum Beispiel in deinem Browser ausführen. Es werden alle aktuellen | ||
+ | Jobs angezeigt, pro Job zwei Zeilen. Die erste Zeile enthält die Attribute des Jobs (Position, Wiederholungen, | ||
+ | ecmd/Callback-Job, UTC-Zeit, u.s.w.), in der zweiten Zeile werden die Zeitdaten (MIN HOUR DAY MONTH DAYOFWEEK) | ||
+ | und der ecmd Befehl bzw. die Callback Addresse angezeigt. | ||
+ | |||
+ | === Remove jobs via ecmd === | ||
+ | '''cron rm N''' entfernt den Nten Job (fängt bei 0 an zu zählen) aus der cron Liste. Vorsicht! '''cron rm''' | ||
+ | ohne Parameter entfernt ALLE cron jobs, und das ohne vorher nachzufragen! | ||
+ | |||
+ | === Add jobs via ecmd === | ||
+ | '''cron add MIN HOUR DAY MONTH DAYOFWEEK ECMD''' | ||
+ | |||
+ | MIN HOUR DAY MONTH und DAYOFWEEK können -1 (als Platzhalterfunktion) annehmen. | ||
+ | |||
+ | ECMD: Der ecmd Befehl, der ausgeführt werden soll. | ||
+ | |||
+ | Nach dem Anlegen wird die Position des neuen Jobs in der Liste ausgegeben. | ||
+ | |||
+ | === Mark job as persistent via ecmd === | ||
+ | '''cron persistent N 1''' macht den Nten Job persistent | ||
+ | |||
+ | '''cron persistent N 0''' löscht das persistent flag | ||
+ | |||
+ | '''cron persistent N''' zeigt den aktuellen Status an | ||
+ | |||
+ | === Write persistent jobs to VFS/EEPROM via ecmd === | ||
+ | '''cron save''' alle als persistent markierten Jobs werden im VFS/EEPROM abgespeichert. | ||
+ | |||
+ | === Mark job for UTC time via ecmd === | ||
+ | '''cron utc N 1''' setzt den Nten Job auf UTC | ||
+ | |||
+ | '''cron utc N 0''' löscht das UTC flag | ||
+ | |||
+ | '''cron utc N''' zeigt den aktuellen Status an | ||
+ | |||
+ | === Mark job as anacron job via ecmd === | ||
+ | |||
+ | Dieses Flag bietet eine Art anacron-Funktion. Gedacht ist dies für Jobs, die bestimmte Stati setzen. | ||
+ | Ein Beispiel wäre die Zirkulationspumpe einer Heizung. Angenommen die Pumpe soll um 6.00 Uhr | ||
+ | eingesaltet und um 9.00 wieder ausgeschaltet werden, könnte das natürlich auch mit normalen Jobs | ||
+ | erledigt werden. Sollte der Controller allerdings um 7.00 neu booten (z.B. wg. Stromausfall) bliebe | ||
+ | Pumpe bis zum nächsten Tag 6.00 ausgeschaltet. Ähnliches gilt für grössere Zeitsprünge durch NTP-Updates. | ||
+ | |||
+ | Um das Problem zu lösen, werden alle anacron-Jobs nachgezogen, die innerhalb des übersprungenen Zeitraums | ||
+ | (also vom 1.1.1970 bis zur aktuellen Zeit im Falle das Boots) hätten ausgeführt werden müssen, wobei jeder | ||
+ | Job nur einmal ausgeführt wird und auch in der korrekten Reihenfolge (jüngstes Ausführungsdatum zählt). | ||
+ | Damit die Schleife zum Ermitteln der Jobs nicht unnötig lange dauert, ist der Startzeitpunkt in der | ||
+ | Vergangenheit auf <Aktuelle Zeit> - CRON_ANACRON_MAXAGE Sekunden beschränkt. Voreingestellt ist hier | ||
+ | ein Tag (86400 Sekunden). | ||
+ | |||
+ | '''cron anacron N 1''' markiere den Nten Job als anacron Job | ||
+ | |||
+ | '''cron anacron N 0''' löscht das UTC flag | ||
+ | |||
+ | '''cron anacron N''' zeigt den aktuellen Status an | ||
+ | |||
+ | === Define cronjob in source code: callback function === | ||
+ | Wer scharf hinsieht, erkennt, dass diese Funktionalität auch durch den statischen Cron Daemon abgedeckt wird. | ||
+ | Der statische Dienst verbraucht dabei sogar weniger Ressourcen. Aber, hier die Vorteile des dynamischen Dienstes: | ||
+ | |||
+ | * Du musst keinen Quelltext in ein fremdes Modul einfügen (Übersichtlichkeit der cron_static.c nimmt mit jedem weiterem Modul ab) | ||
+ | * Du kannst zur Laufzeit den cronjob auch wieder entfernen. | ||
+ | * Du kannst Extradaten an die Callback Funktion übergeben | ||
+ | |||
+ | Die Funktion, welche der Daemon aufrufen soll, muss folgende Signatur haben | ||
+ | '''void func(char* data)''' und sollte ''nicht'' in der cron/cron.c Datei definiert werden, sondern in dem | ||
+ | jeweiligen Modul, welche die Cron Funktionalität nutzen will. | ||
+ | |||
+ | # Binde in dein Modul die Datei 'cron/cron.h' ein. | ||
+ | # Nutze die Callback Variante des Cron-Einfügen Befehls '''cron_jobinsert_callback''' in der Initalisierungsfunktion deines Moduls um beim Start von ethersex cronjobs hinzuzufügen. | ||
+ | # Die Funktionsparameter haben die folgende Semantik: | ||
+ | * Minute, -1 für ignorieren, -2 für jede 2te Minute etc | ||
+ | * Stunde, -1 für ignorieren, -2 für jede 2te Stunde etc | ||
+ | * Tag, -1 für ignorieren, -2 für jeden 2te Tag etc | ||
+ | * Monat, -1 für ignorieren, -2 für jeden 2te Monat etc | ||
+ | * Wochentag, 1 für Sonntag, 2 für Montag, 4 für Dienstag, 8 für Mittwoch, 16 für Donnerstag, 32 für Freitag, 64 für Samstag oder eine Addition daraus | ||
+ | * Wiederholen, INFINIT_RUNNING für endlos, 1=einmal etc | ||
+ | * Position des Crons in der Cronliste (CRON_APPEND, wenn angehängt werden soll) | ||
+ | * Callback Funktion | ||
+ | * Größe von Extradaten | ||
+ | * Extradaten | ||
+ | |||
+ | Beispiel aus der Test Einträge Datei: | ||
+ | void test(void* data) { /* tu was */ } | ||
+ | // in init | ||
+ | cron_jobinsert_callback(-1, -2, -1, -1, -1, INFINIT_RUNNING, CRON_APPEND, test, 0, NULL); | ||
+ | |||
+ | Extradaten sind eine ziemlich coole Sache. Stella PWM zum Beispiel speichert darin Lichtkanal und Zielwert. | ||
+ | Beim Aktivieren des Cronjobs wird der Zeiger auf diese Extradaten dann an die Callback Funktion mit übergeben | ||
+ | und diese stehen direkt zur Verfügung. | ||
+ | Bitte beachte hierbei aber, dass der Pointer auf die Extradaten durch einen Malloc Aufruf gewonnen werden muss, | ||
+ | sprich die Speicherstelle für die Extradaten müssen vorher auf dem Heap allokiert werden. | ||
+ | (Beispiel: '''char* extra = malloc(2);''' für 2 Bytes auf dem Heap) | ||
+ | |||
+ | Du musst und solltest dich nicht um die Freigabe des allokierten Speichers kümmern. | ||
+ | Dies erledigt der Cron daemon bereits. | ||
+ | |||
+ | === Define cronjob in source code: ecmd command === | ||
+ | Der statische cron daemon bot die Möglichkeit eine Funktion zu gegebenem Zeitpunkt aufzurufen. Wenn du jedoch | ||
+ | den dynamischen Dienst nutzt, kannst du auch ecmd Befehle zeitabhängig aufrufen lassen | ||
+ | (z.B. Pins setzen, Stella PWM kontrollieren, ethersex reseten etc). | ||
+ | |||
+ | Die Funktion die du in dein Modul hierfür einbauen musst, lautet folgendermaßen: | ||
+ | |||
+ | cron_jobinsert_ecmd(-1, -2, -1, -1, 127, INFINIT_RUNNING, CRON_APPEND, "ECMD"); |
Revision as of 09:06, 5 April 2012
Cron daemon | |
---|---|
Status | Stable
|
menuconfig | Applications->Cron daemon |
Pinning | no |
Ecmd | yes |
Depends on | ECMD, Clock |
Code | https://github.com/ethersex/ethersex/tree/master/services/cron |
Cron daemon manage cron jobs. This rules define repeated or unique events that call certain commands.
Cron jobs are implemented in two flavors: a static list that is defined at compile time and not changeable at runtime, and a dynamic approach, which loads the joblist to the RAM at statup. Jobs can be added and removed at runtime.
Contents
- 1 Preconditions
- 2 Menuconfig
- 3 Static Cron Daemon
- 4 Dynamic Cron Daemon
- 4.1 View jobs via ecmd
- 4.2 Remove jobs via ecmd
- 4.3 Add jobs via ecmd
- 4.4 Mark job as persistent via ecmd
- 4.5 Write persistent jobs to VFS/EEPROM via ecmd
- 4.6 Mark job for UTC time via ecmd
- 4.7 Mark job as anacron job via ecmd
- 4.8 Define cronjob in source code: callback function
- 4.9 Define cronjob in source code: ecmd command
Preconditions
Beide Ansätze haben gemeinsam, dass du erst einmal eine Funktion definieren musst, welche vom Cron daemon zum bestimmten Zeitpunkt aufgerufen werden kann. Die Funktionssignatur sieht allerdings, abhängig davon welche Implementierung du wählst, leicht anders aus.
Menuconfig
Das Modul benötigt allerdings die aktuelle Zeit um richtig funktionieren zu können. Du musst daher im selben Untermenü mindestens eine Zeitquelle ebenfalls einschalten. Um Crontabs in ethersex zu aktivieren, wählt man im Menü
│ │ Load a Default Configuration ---> │ │ ... │ │ Applications ---> │ │ ... │ │ [*] Cron daemon ---> │ │ [ ] Cron daemon (static jobs)
Static Cron Daemon
Die Funktion, welche der Daemon aufrufen soll, muss folgende Signatur haben void func(void) und muss direkt in cron_static/cron_static.c definiert werden.
Es muss dann nur noch eine Regel in die Array Struktur events vom Typ cron_static_event_t eingefügt werden. Die Werte der Reihenfolge nach stehen für Minute, Stunde, Tag, Monat, Wochentag, Callback Funktion und ob UTC oder die lokale Zeitzone benutzt werden soll.
Eine -1 steht für einen Platzhalter. Da die Einträge ca. jede Minute einmal geprüft werden, wird also ein Eintrag mit nur Platzhalter Werten auch ca. jede Minute ausgeführt.
Werte unter -1 haben die Bedeutung von "jede x-te Minute/Stunde/etc". Also ein Wert von -4 an der Minutenstelle bedeutet, dass der Crontab jede 4te Minute ausgeführt wird.
Dynamic Cron Daemon
View jobs via ecmd
Einfach den ecmd Befehl cron list zum Beispiel in deinem Browser ausführen. Es werden alle aktuellen Jobs angezeigt, pro Job zwei Zeilen. Die erste Zeile enthält die Attribute des Jobs (Position, Wiederholungen, ecmd/Callback-Job, UTC-Zeit, u.s.w.), in der zweiten Zeile werden die Zeitdaten (MIN HOUR DAY MONTH DAYOFWEEK) und der ecmd Befehl bzw. die Callback Addresse angezeigt.
Remove jobs via ecmd
cron rm N entfernt den Nten Job (fängt bei 0 an zu zählen) aus der cron Liste. Vorsicht! cron rm ohne Parameter entfernt ALLE cron jobs, und das ohne vorher nachzufragen!
Add jobs via ecmd
cron add MIN HOUR DAY MONTH DAYOFWEEK ECMD
MIN HOUR DAY MONTH und DAYOFWEEK können -1 (als Platzhalterfunktion) annehmen.
ECMD: Der ecmd Befehl, der ausgeführt werden soll.
Nach dem Anlegen wird die Position des neuen Jobs in der Liste ausgegeben.
Mark job as persistent via ecmd
cron persistent N 1 macht den Nten Job persistent
cron persistent N 0 löscht das persistent flag
cron persistent N zeigt den aktuellen Status an
Write persistent jobs to VFS/EEPROM via ecmd
cron save alle als persistent markierten Jobs werden im VFS/EEPROM abgespeichert.
Mark job for UTC time via ecmd
cron utc N 1 setzt den Nten Job auf UTC
cron utc N 0 löscht das UTC flag
cron utc N zeigt den aktuellen Status an
Mark job as anacron job via ecmd
Dieses Flag bietet eine Art anacron-Funktion. Gedacht ist dies für Jobs, die bestimmte Stati setzen. Ein Beispiel wäre die Zirkulationspumpe einer Heizung. Angenommen die Pumpe soll um 6.00 Uhr eingesaltet und um 9.00 wieder ausgeschaltet werden, könnte das natürlich auch mit normalen Jobs erledigt werden. Sollte der Controller allerdings um 7.00 neu booten (z.B. wg. Stromausfall) bliebe Pumpe bis zum nächsten Tag 6.00 ausgeschaltet. Ähnliches gilt für grössere Zeitsprünge durch NTP-Updates.
Um das Problem zu lösen, werden alle anacron-Jobs nachgezogen, die innerhalb des übersprungenen Zeitraums (also vom 1.1.1970 bis zur aktuellen Zeit im Falle das Boots) hätten ausgeführt werden müssen, wobei jeder Job nur einmal ausgeführt wird und auch in der korrekten Reihenfolge (jüngstes Ausführungsdatum zählt). Damit die Schleife zum Ermitteln der Jobs nicht unnötig lange dauert, ist der Startzeitpunkt in der Vergangenheit auf <Aktuelle Zeit> - CRON_ANACRON_MAXAGE Sekunden beschränkt. Voreingestellt ist hier ein Tag (86400 Sekunden).
cron anacron N 1 markiere den Nten Job als anacron Job
cron anacron N 0 löscht das UTC flag
cron anacron N zeigt den aktuellen Status an
Define cronjob in source code: callback function
Wer scharf hinsieht, erkennt, dass diese Funktionalität auch durch den statischen Cron Daemon abgedeckt wird. Der statische Dienst verbraucht dabei sogar weniger Ressourcen. Aber, hier die Vorteile des dynamischen Dienstes:
- Du musst keinen Quelltext in ein fremdes Modul einfügen (Übersichtlichkeit der cron_static.c nimmt mit jedem weiterem Modul ab)
- Du kannst zur Laufzeit den cronjob auch wieder entfernen.
- Du kannst Extradaten an die Callback Funktion übergeben
Die Funktion, welche der Daemon aufrufen soll, muss folgende Signatur haben void func(char* data) und sollte nicht in der cron/cron.c Datei definiert werden, sondern in dem jeweiligen Modul, welche die Cron Funktionalität nutzen will.
- Binde in dein Modul die Datei 'cron/cron.h' ein.
- Nutze die Callback Variante des Cron-Einfügen Befehls cron_jobinsert_callback in der Initalisierungsfunktion deines Moduls um beim Start von ethersex cronjobs hinzuzufügen.
- Die Funktionsparameter haben die folgende Semantik:
- Minute, -1 für ignorieren, -2 für jede 2te Minute etc
- Stunde, -1 für ignorieren, -2 für jede 2te Stunde etc
- Tag, -1 für ignorieren, -2 für jeden 2te Tag etc
- Monat, -1 für ignorieren, -2 für jeden 2te Monat etc
- Wochentag, 1 für Sonntag, 2 für Montag, 4 für Dienstag, 8 für Mittwoch, 16 für Donnerstag, 32 für Freitag, 64 für Samstag oder eine Addition daraus
- Wiederholen, INFINIT_RUNNING für endlos, 1=einmal etc
- Position des Crons in der Cronliste (CRON_APPEND, wenn angehängt werden soll)
- Callback Funktion
- Größe von Extradaten
- Extradaten
Beispiel aus der Test Einträge Datei:
void test(void* data) { /* tu was */ } // in init cron_jobinsert_callback(-1, -2, -1, -1, -1, INFINIT_RUNNING, CRON_APPEND, test, 0, NULL);
Extradaten sind eine ziemlich coole Sache. Stella PWM zum Beispiel speichert darin Lichtkanal und Zielwert. Beim Aktivieren des Cronjobs wird der Zeiger auf diese Extradaten dann an die Callback Funktion mit übergeben und diese stehen direkt zur Verfügung. Bitte beachte hierbei aber, dass der Pointer auf die Extradaten durch einen Malloc Aufruf gewonnen werden muss, sprich die Speicherstelle für die Extradaten müssen vorher auf dem Heap allokiert werden. (Beispiel: char* extra = malloc(2); für 2 Bytes auf dem Heap)
Du musst und solltest dich nicht um die Freigabe des allokierten Speichers kümmern. Dies erledigt der Cron daemon bereits.
Define cronjob in source code: ecmd command
Der statische cron daemon bot die Möglichkeit eine Funktion zu gegebenem Zeitpunkt aufzurufen. Wenn du jedoch den dynamischen Dienst nutzt, kannst du auch ecmd Befehle zeitabhängig aufrufen lassen (z.B. Pins setzen, Stella PWM kontrollieren, ethersex reseten etc).
Die Funktion die du in dein Modul hierfür einbauen musst, lautet folgendermaßen:
cron_jobinsert_ecmd(-1, -2, -1, -1, 127, INFINIT_RUNNING, CRON_APPEND, "ECMD");