Skip to content

Scheduler ​

Statt je INI-Datei einen eigenen Task im Windows Task Scheduler anzulegen, wird in jeder INI-Datei eine Sektion [timer] angegeben. Die Syntax lehnt sich an systemd Timer an.

INI-Sektion: timer ​

ini
[timer]
OnCalendar = *:0/15
KeyBeispielBeschreibung
OnCalendar **:0/15Ein oder mehrere Zeitpunkte H:M[:S] (durch Leerzeichen getrennt) bzw. minutely, hourly, daily
RandomizedDelaySec0 oder 5mMaximale Verzögerung zur Lastverteilung; die Verzögerung ist je INI-Datei fix (default: Intervall, höchstens 1m)
RuntimeMaxSec2hEin Lauf, der länger dauert, wird abgebrochen (default: Intervall, mindestens 5m, höchstens 1h)
PersistentTrueTrue: ein verpasster Zeitpunkt (z. B. Server war ausgeschaltet) wird beim Start nachgeholt (default True für tägliche Jobs)

Jedes Feld von H:M:S unterstützt *, 6, 6,12,18, 8..17 und 0/15 (ab 0 alle 15). Wochentage und Datumsangaben werden nicht unterstützt.

JobOnCalendar
täglich06:00
mehrmals täglich06,12,18:00 oder 06:00 12:30 18:00
stündlichhourly (= *:00)
alle 15 min*:0/15
alle 10 min*:0/10
jede Minuteminutely (= *:*)
alle 20 s*:*:0/20

Timer prüfen ​

Ähnlich wie systemctl list-timers werden die nächsten Zeitpunkte jeder INI-Datei ausgegeben:

powershell
> python prozessing.pyz --timers ini\*.ini
conv_gprssommer      OnCalendar=*:0/15 delay=0:00:17 RuntimeMaxSec=0:15:00 next=2026-10-06 10:15:17, 2026-10-06 10:30:17, 2026-10-06 10:45:17
ftp_in_example       no [timer]

Scheduler starten ​

powershell
> python prozessing.pyz --scheduler "ini\*.ini"
  • Jede INI-Datei mit [timer] wird als eigener Prozess gestartet; ein hängender oder abstürzender Job beeinflusst die anderen Jobs nicht.
  • Läuft ein Job zum nächsten Zeitpunkt noch, wird dieser Zeitpunkt übersprungen. Überschreitet ein Job RuntimeMaxSec, wird er samt Unterprozessen (curl, rclone, WinSCP, …) beendet.
  • Es laufen höchstens max(4, Anzahl CPUs) Jobs gleichzeitig.
  • Neue, geänderte und gelöschte INI-Dateien werden laufend übernommen, das Muster daher in Anführungszeichen angeben.
  • Der Scheduler protokolliert nach logs/scheduler_{date}.log, jeder Job wie bisher nach logs/{file}_{date}.log.

Laufprotokoll ​

Jeder Lauf wird als eine JSON-Zeile in logs/runs_{date}.jsonl (je Kalendertag, entsprechend --logfile) protokolliert:

json
{"ini": "conv_gprssommer", "start": "2026-10-06T10:15:17", "duration": 2, "status": "ok", "exit_code": 0, "error": null, "fetched": 3, "converted": 3}
  • status: ok, failed, timeout (abgebrochen nach RuntimeMaxSec) oder skipped (lief noch)
  • error: letzte Warnung bzw. Fehlermeldung des Jobs
  • fetched, sent, converted, failed: Anzahl abgeholter, versendeter, konvertierter und fehlerhafter Dateien (bei sftp_rclone nicht verfügbar)

Alte Laufprotokolle können wie Log-Dateien per [delete] gelöscht werden.

Dateiprotokoll ​

Jede abgeholte, versendete, konvertierte bzw. fehlerhafte Datei wird als eine JSON-Zeile in logs/files_{date}.jsonl protokolliert (auch ohne Scheduler):

json
{"time": "2026-10-15T10:15:18", "job": "conv_gprssommer.CONV", "kind": "converted", "src": "D:\\Daten\\spool\\gprssommer\\archiv.zip", "size": 1234, "owner": null, "error": null, "headers": [{"dest": "D:\\Daten\\zrxp\\archiv.zip.zrxp", "exchange": "123_W", "count": 96, "from": "2026-10-14 10:15:00", "to": "2026-10-15 10:00:00", "last": 1.23, "unit": "cm"}]}
  • kind: fetched, sent, converted, graphics (erstellte Grafik) oder failed
  • src: Quelldatei bzw. URL; dest: Zieldateien bei der Datenabholung
  • owner: Besitzer der Quelldatei bei LOG_OWNER = True
  • headers: geschriebene ZRXP-Blöcke mit Austauschnummer, Werteanzahl, Zeitraum, Letztwert und Einheit

Unter Windows genügt ein einziger Task im Task Scheduler ohne Laufzeitlimit. Er startet beim Systemstart und wird alle 5 Minuten neu gestartet, falls er nicht (mehr) läuft:

xml
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <Triggers>
    <BootTrigger><Enabled>true</Enabled></BootTrigger>
    <TimeTrigger>
      <Repetition><Interval>PT5M</Interval></Repetition>
      <StartBoundary>2000-01-01T00:00:00</StartBoundary>
      <Enabled>true</Enabled>
    </TimeTrigger>
  </Triggers>
  <Settings>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>D:\TBBM\python\python.exe</Command>
      <Arguments>prozessing.pyz --scheduler "ini\*.ini"</Arguments>
      <WorkingDirectory>D:\TBBM\PROZESSING</WorkingDirectory>
    </Exec>
  </Actions>
</Task>