<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cronjob on wt-modules</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/</link><description>Recent content in Cronjob on wt-modules</description><generator>Hugo</generator><language>de</language><atom:link href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/index.xml" rel="self" type="application/rss+xml"/><item><title>Verwendung</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/usage/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/usage/</guid><description>&lt;h2 id="job-erstellen"&gt;Job erstellen&lt;a class="td-heading-self-link" href="#job-erstellen" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;Steuerungspanel → Cron Job Scheduler → Neuer Job&lt;/code&gt;:&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Feld&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th style="text-align: left"&gt;Bedeutung&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Name (Slug)&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;technischer Bezeichner, &lt;code&gt;a-z 0-9 _ -&lt;/code&gt;. &lt;strong&gt;Nur-lesen für &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/howto-use/self-registration/"&gt;durch Module angebotene Jobs&lt;/a&gt;&lt;/strong&gt; (deren &lt;code&gt;&amp;lt;module&amp;gt;:&amp;lt;name&amp;gt;&lt;/code&gt;-Schlüssel ist fix); editierbar für selbst erstellte Jobs.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Titel&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;menschenlesbarer Name&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein oder mehrere &lt;strong&gt;Zeit-Trigger&lt;/strong&gt; (Cron-Zeitpläne) und/oder &lt;strong&gt;Ereignis-Trigger&lt;/strong&gt; — der Job feuert, wenn &lt;em&gt;irgendein&lt;/em&gt; Trigger feuert. Mindestens einer ist erforderlich.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Cron-Ausdruck&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;(Zeit-Trigger) Standard-5-Feld-Cron oder ein Makro (&lt;code&gt;@daily&lt;/code&gt;, &lt;code&gt;@weekly&lt;/code&gt;, …). &lt;strong&gt;Zeiten sind UTC.&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Ereignisname&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;(Ereignis-Trigger) das &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/"&gt;Ereignis&lt;/a&gt;, auf das dieser Job reagiert. Slug oder &lt;code&gt;&amp;lt;domain&amp;gt;:slug&lt;/code&gt;, max. 64 Zeichen.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Befehl&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;ein &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&amp;lt;script&amp;gt;.php&lt;/code&gt;-Pfad oder ein erlaubter Core-Befehl.&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Argumente&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;nur einfache Optionen/Werte (z.B. &lt;code&gt;--limit=5000&lt;/code&gt;), max. 10 Tokens&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Timeout&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;30 - 3600 s&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;&lt;strong&gt;Bei Fehler benachrichtigen&lt;/strong&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td style="text-align: left"&gt;Opt-in: Admin-Konten bei Job-Fehlern benachrichtigen&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Verfügbare Ereignisnamen und Befehle werden als Datalists bereitgestellt, um die Dateneingabe zu erleichtern.&lt;/p&gt;</description></item><item><title>Der Tick</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/</guid><description>&lt;p&gt;Der &lt;strong&gt;Tick&lt;/strong&gt; ist das Herz des Moduls: einmal pro Minute prüft er alle aktivierten Jobs, entscheidet, was fällig ist, und führt es aus. Weder das webtrees-Core noch das Betriebssystem planen selbst — sie starten nur &lt;a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/tick.php" target="_blank" rel="noopener"&gt;&lt;code&gt;tick.php&lt;/code&gt;&lt;/a&gt;&#10;.&lt;/p&gt;&#10;&#10;&#10;&#10;&lt;pre class="mermaid"&gt;flowchart TD&#10; subgraph Triggers[&amp;#34;`⏱ Auslöser *(once per minute)*`&amp;#34;]&#10; CRON[&amp;#34;`🕑 OS cron / systemd&amp;lt;br/&amp;gt;*every minute*`&amp;#34;]&#10; WATCH[&amp;#34;`👁 watch-Daemon&amp;lt;br/&amp;gt;*(in-module)*`&amp;#34;]&#10; end&#10;&#10; subgraph Guard[&amp;#34;🛡 Guard&amp;#34;]&#10; TP[&amp;#34;`📄 cli/tick.php · **cron:tick**&amp;lt;br/&amp;gt;*guard(): 403 over HTTP*`&amp;#34;]&#10; OFF{&amp;#34;`⚠ site offline?&amp;lt;br/&amp;gt;*data/offline.txt*`&amp;#34;}&#10; BOOT[&amp;#34;`🚀 boot()&amp;lt;br/&amp;gt;*webtrees &amp;#43; DB*`&amp;#34;]&#10; end&#10;&#10; subgraph Selection[&amp;#34;🔎 Arbeit auswählen&amp;#34;]&#10; TIME[&amp;#34;`📅 time-based jobs&amp;lt;br/&amp;gt;**next_run_at due** *(UTC)*`&amp;#34;]&#10; CE[(&amp;#34;`📦 cj_event&amp;lt;br/&amp;gt;*Event-Warteschlange*`&amp;#34;)]&#10; DRAIN[&amp;#34;`🧮 drain queue&amp;lt;br/&amp;gt;*coalesced · 60 s budget*`&amp;#34;]&#10; end&#10;&#10; subgraph Execution[&amp;#34;`⚙ Ausführung *(isolated child)*`&amp;#34;]&#10; RUN[&amp;#34;`🧪 JobRunner&amp;lt;br/&amp;gt;**proc_open**`&amp;#34;]&#10; LIM[&amp;#34;`⏲ timeout 30–3600 s&amp;lt;br/&amp;gt;last **64 KB** · exit code`&amp;#34;]&#10; end&#10;&#10; subgraph Storage[&amp;#34;💾 Speicherung&amp;#34;]&#10; CJRUN[(&amp;#34;`cj_run&amp;lt;br/&amp;gt;*Laufverlauf*`&amp;#34;)]&#10; MARK[&amp;#34;`🏷 tick.last&amp;lt;br/&amp;gt;*stale &amp;gt; 300 s → tick_stale*`&amp;#34;]&#10; end&#10;&#10; CRON --&amp;gt; Guard&#10; WATCH --&amp;gt; Guard&#10; TP --&amp;gt; OFF&#10; OFF --&amp;gt;|&amp;#34;offline&amp;#34;| SKIP[&amp;#34;⏭ Tick überspringen&amp;#34;]&#10; OFF --&amp;gt;|&amp;#34;online&amp;#34;| BOOT&#10; BOOT --&amp;gt; TIME&#10; BOOT --&amp;gt; DRAIN&#10; CE --&amp;gt; DRAIN&#10; TIME --&amp;gt; Execution&#10; DRAIN --&amp;gt; Execution&#10; RUN --&amp;gt; LIM&#10; LIM --&amp;gt; CJRUN&#10; BOOT --&amp;gt; MARK&#10;&#10; classDef sourceStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px&#10; classDef queueStyle fill:#fff3e0,stroke:#E65100,stroke-width:2px&#10; classDef tickStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px&#10; classDef execStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px&#10; classDef storageStyle fill:#f5f5f5,stroke:#616161,stroke-width:1px&#10;&#10; class CRON,WATCH sourceStyle&#10; class OFF,CE queueStyle&#10; class TP,TIME,DRAIN tickStyle&#10; class RUN,LIM execStyle&#10; class CJRUN,MARK,SKIP storageStyle&#10;&lt;/pre&gt;&#10;&lt;h2 id="was-einen-tick-startet"&gt;Was einen Tick startet&lt;a class="td-heading-self-link" href="#was-einen-tick-startet" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;Einen Trigger wählen (einmalig):&lt;/p&gt;</description></item><item><title>CLI-Skripte</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/</guid><description>&lt;h2 id="skripte"&gt;Skripte&lt;a class="td-heading-self-link" href="#skripte" aria-label="Heading self-link"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php &lt;span style="color:#6e738d;font-style:italic"&gt;# alle fälligen Jobs ausführen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --dry-run &lt;span style="color:#6e738d;font-style:italic"&gt;# anzeigen, was ausgeführt würde&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --job&lt;span style="color:#91d7e3;font-weight:bold"&gt;=&lt;/span&gt;&amp;lt;name&amp;gt; &lt;span style="color:#6e738d;font-style:italic"&gt;# einen bestimmten Job jetzt ausführen&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --strict &lt;span style="color:#6e738d;font-style:italic"&gt;# Exit 1 wenn ein Job fehlgeschlagen ist&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/tick.php --full-output &lt;span style="color:#6e738d;font-style:italic"&gt;# vollständige Job-Ausgabe echo (Debugging!)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;php modules_v4/cronjob/cli/watch.php &lt;span style="color:#6e738d;font-style:italic"&gt;# Watch-Daemon starten&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Exit-Codes: &lt;code&gt;0&lt;/code&gt; = Tick lief (Job-Fehler werden in der DB protokolliert), &lt;code&gt;1&lt;/code&gt; = Umgebungsproblem oder (mit &lt;code&gt;--strict&lt;/code&gt;) mindestens ein Job fehlgeschlagen.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;Log-Hygiene:&lt;/strong&gt; stdout trägt nur Summary-Zeilen. Die vollständige Job-Ausgabe liegt in der Ausführungshistorie (nur Admin). &lt;code&gt;--full-output&lt;/code&gt; niemals in einen weltlesbaren Ort umleiten.&lt;/p&gt;</description></item><item><title>Sicherheit</title><link>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/security/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/security/</guid><description>&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Nie eine Shell.&lt;/strong&gt; Befehle werden via &lt;a href="https://www.php.net/manual/de/function.proc-open.php"&gt;&lt;code&gt;proc_open&lt;/code&gt;&lt;/a&gt; mit einem &lt;a href="https://www.php.net/manual/de/reserved.variables.argv.php"&gt;argv-Array&lt;/a&gt; ausgeführt.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Befehls-Whitelist.&lt;/strong&gt; &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/cli-scripts/"&gt;Modulskripte&lt;/a&gt; müssen &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&amp;lt;script&amp;gt;.php&lt;/code&gt; entsprechen, existieren und sich in einem &lt;code&gt;modules_v4/&amp;lt;module&amp;gt;/cli/&lt;/code&gt;-Verzeichnis auflösen. Core-Befehle sind auf die Read-only/Export-Allowlist beschränkt.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Argument-Validierung.&lt;/strong&gt; Jedes Argument-Token muss eine einfache Option oder ein Wert sein — keine Shell-Metazeichen, keine Leerzeichen in Tokens, max. 10 Tokens.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Arbeitsverzeichnisse.&lt;/strong&gt; Modulskripte laufen vom webtrees-Root; Core-Befehle laufen von &lt;code&gt;data/&lt;/code&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Keine sensiblen Daten in stdout.&lt;/strong&gt; Der &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/tick/"&gt;Tick&lt;/a&gt; gibt nur Zusammenfassungen aus; die vollständige Ausgabe bleibt in der Ausführungshistorie (admin-only).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;UI-Aktionen&lt;/strong&gt; sind alle als &lt;code&gt;*Admin*&lt;/code&gt; benannt (nur Admin, &lt;a href="https://developer.mozilla.org/de/docs/Web/Security/Attacks/CSRF"&gt;CSRF&lt;/a&gt;-geschützt).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Notaus-Schalter:&lt;/strong&gt; Modul deaktivieren — der Tick tut dann nichts.&lt;/li&gt;&#10;&lt;li&gt;Der Tick ist Single-Instance (flock), und der Kindprozess eines Jobs wird nach dem Timeout hart getötet (&lt;a href="https://de.wikipedia.org/wiki/SIGKILL"&gt;&lt;code&gt;SIGKILL&lt;/code&gt;&lt;/a&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Bündelung von Ereigniswarteschlangen.&lt;/strong&gt; Eine Flut identischer &lt;a href="https://bschwede.codeberg.page/wt-modules/de/docs/cronjob/events/"&gt;Ereignisse&lt;/a&gt; wird zusammengeführt zu einem Joblauf.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Webhook-Token nur im Header.&lt;/strong&gt; Das Token wird ausschließlich im &lt;code&gt;X-Cronjob-Token&lt;/code&gt;-Header gesendet.&lt;/li&gt;&#10;&lt;/ul&gt;</description></item></channel></rss>