Takt über public/cron.php: KAS-Cronjobs können nur URLs

Korrektur meiner eigenen Annahme von heute früh. Der Tarif hat SSH und
Cronjobs, aber das KAS-Formular kennt nur ein Feld "Protokoll / Pfad" mit
https:// — ein `php bin/…` ist dort nicht eintragbar. Der Endpoint, den ich
vorhin stillgelegt hatte, ist damit wieder der einzige Takt-Geber, und zwar in
einer besseren Form als geplant: Aufrufer ist der Hoster selbst, der Schlüssel
verlässt den Webspace nie, kein Dritter ist beteiligt.

Dritter Job 'logrotate' in der Whitelist, denn ohne ihn liefe die Logpflege nie
automatisch und die 2-MB-Grenze samt 90-Tage-Frist wäre toter Code. Er passt in
denselben Rahmen wie die Syncs: kein Parameter aus der URL, keine Verbindung nach
außen, schreibt nur in storage/logs. bin/log-rotate.php trägt dafür denselben
Riegel wie die Syncs (CRON_HTTP) und require_once. Eine vierte Ausnahme braucht
wieder denselben Aufwand an Begründung.

Geprüft: falscher Schlüssel 403, unbekannter Job 403, gültiger Aufruf 204 mit
leerem Body, sofortige Wiederholung 204 plus WARN, Logdateien unversehrt.

Zeitraster angepasst, weil das KAS Wochentage nicht mit Halbstunden kombiniert:
Matchcenter stündlich statt 2x/Tag plus Wochenende, Instagram als zwei
Tageseinträge, Logpflege täglich nachts. Die Abwägung steht in
config.example.php und docs/deploy.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
This commit is contained in:
2026-07-31 17:16:12 +02:00
parent 964ffb932b
commit 05c64c8f12
5 changed files with 133 additions and 94 deletions

View File

@@ -255,35 +255,53 @@ führen (macOS NFD gegen Linux NFC).
## Teil D — Cronjobs
Erst jetzt, damit ab dem Umschalten schon frische Daten liegen. `SITE` und der
PHP-Pfad kommen aus B1/B2.
**Die KAS-Cronjobs können nur URLs aufrufen, keine Shell-Befehle** (geprüft 31.07.2026:
das Formular hat ein Feld „Protokoll / Pfad" mit `https://`, kein Kommandofeld). Der
Takt läuft deshalb über `public/cron.php`. Aufrufer ist der Hoster selbst — der
Schlüssel verlässt den Webspace nie, kein Dritter ist beteiligt.
[KAS] → **Cronjobs** → eigener Cronjob (Shell), vier Einträge:
Voraussetzung: `cron.key` muss in `config/config.php` gesetzt sein (48 Zeichen,
nicht `app_secret`). Steht er leer, antwortet der Endpoint mit 403 und **nichts** synct.
`bin/preflight.php` prüft Länge und Verwechslung.
```
# Instagram 2x/Tag
17 6,18 * * * cd SITE && PHP bin/instagram-sync.php >> storage/logs/instagram.log 2>&1
[KAS] → **Cronjobs** → Anlegen, drei bis vier Einträge. `KEY` durch den Wert aus
`config.php` ersetzen:
# Matchcenter Grundtakt 2x/Tag
37 7,19 * * * cd SITE && PHP bin/matchcenter-sync.php >> storage/logs/matchcenter.log 2>&1
| # | Pfad | Zeitpunkt |
|---|---|---|
| 1 | `www.tsv08kulmbach.de/cron.php?job=matchcenter&key=KEY` | stündlich, Minute 37 |
| 2 | `www.tsv08kulmbach.de/cron.php?job=instagram&key=KEY` | täglich, 06:17 |
| 3 | `www.tsv08kulmbach.de/cron.php?job=instagram&key=KEY` | täglich, 18:17 |
| 4 | `www.tsv08kulmbach.de/cron.php?job=logrotate&key=KEY` | täglich, 03:23 |
# Matchcenter am Spieltag halbstuendlich (Sa+So 13-21 Uhr)
7,37 13-21 * * 6,0 cd SITE && PHP bin/matchcenter-sync.php >> storage/logs/matchcenter.log 2>&1
Vier Dinge dahinter sind Absicht:
# Logpflege sonntags nachts
23 3 * * 0 cd SITE && PHP bin/log-rotate.php > /dev/null 2>&1
- **Matchcenter stündlich statt halbstündlich am Spieltag.** Das KAS kann Wochentage
nicht mit einem Halbstunden-Takt kombinieren, wie es die ursprüngliche Crontab vorsah.
Stündlich rund um die Uhr ist der brauchbare Ersatz: am Spieltag steht das Ergebnis
spätestens eine Stunde später. Kostet 24 Läufe/Tag. Wer den Verkehr zum BFV klein
halten will, nimmt zwei „täglich"-Jobs (07:37 und 19:37) und lebt damit, dass
Samstagsergebnisse erst abends stehen.
- **Instagram zwei Einträge**, weil „täglich" nur einen Zeitpunkt kennt. Bewusst nicht
stündlich: Instagram sperrt auffällige Zugriffsmuster schneller als der BFV.
- **Versetzte Minuten**, damit sich zwei Läufe nie überlappen (die Syncs sperren sich
per Lock, sonst fällt einer aus).
- **Das E-Mail-Feld im KAS bleibt leer.** Die Antwort ist immer leer (204 = gelaufen oder
wegen Mindestabstand übersprungen, 403 = Schlüssel oder Job falsch), es gäbe also
nichts zu mailen. Ob der Takt läuft, sagt `php bin/logs.php`; `php bin/preflight.php`
warnt, wenn ein Datenstand zu alt wird.
**Am Tag nach dem ersten Lauf** einmal `php bin/logs.php` ansehen. Läuft nichts, ist fast
immer der Schlüssel in der URL falsch oder abgeschnitten. Gegenprobe von Hand:
```bash
curl -s -o /dev/null -w '%{http_code}\n' \
'https://www.tsv08kulmbach.de/cron.php?job=matchcenter&key=KEY'
```
`SITE` und `PHP` durch die echten absoluten Pfade ersetzen, auf diesem Webspace also
`cd /www/htdocs/w01ca75d/tsv08kulmbach-website && /usr/bin/php bin/…`. Die Minuten sind
versetzt, damit sich zwei Läufe nicht überlappen. Alle Skripte sind CLI-only,
sperren sich per Lock gegen Parallelläufe und lassen bei Fehlern den letzten guten
Cache stehen — ein fehlgeschlagener Lauf schadet nie.
Am Tag nach dem ersten Cron-Lauf einmal `php bin/logs.php` ansehen. Läuft nichts,
ist fast immer der PHP-Pfad falsch oder relativ.
---
204 = angenommen, 403 = Schlüssel oder Job falsch. Direkt danach ein zweites Mal
aufgerufen muss es ebenfalls 204 geben — dann hat der Mindestabstand gegriffen und der
Lauf wurde übersprungen, was im Log als WARN steht.
## Teil E — Umschalten auf die Hauptdomain