# CLI-Skripte

> Command-Line-Skripte und Wartung

---

## Skripte

```bash
php modules_v4/cronjob/cli/tick.php              # alle fälligen Jobs ausführen
php modules_v4/cronjob/cli/tick.php --dry-run    # anzeigen, was ausgeführt würde
php modules_v4/cronjob/cli/tick.php --job=<name> # einen bestimmten Job jetzt ausführen
php modules_v4/cronjob/cli/tick.php --strict     # Exit 1 wenn ein Job fehlgeschlagen ist
php modules_v4/cronjob/cli/tick.php --full-output # vollständige Job-Ausgabe echo (Debugging!)
php modules_v4/cronjob/cli/watch.php             # Watch-Daemon starten
```

Exit-Codes: `0` = Tick lief (Job-Fehler werden in der DB protokolliert), `1` = Umgebungsproblem oder (mit `--strict`) mindestens ein Job fehlgeschlagen.

**Log-Hygiene:** stdout trägt nur Summary-Zeilen. Die vollständige Job-Ausgabe liegt in der Ausführungshistorie (nur Admin). `--full-output` niemals in einen weltlesbaren Ort umleiten.

Für die Fehlersuche unterstützt das <a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/tick.php" target="_blank" rel="noopener"><code>tick.php</code></a>
 Skript auch die Parameter `-v` und `-vv`, damit die Konsolen-Ausgabe ausführlicher ausfällt.

## Acceptance-Test

```bash
php modules_v4/cronjob/cli/smoke-job.php            # zeigt ok, Exit 0
php modules_v4/cronjob/cli/smoke-job.php --sleep=10 # lebt 10 s (Timeout-Test)
```

Erstellen Sie einen Job mit Befehl `modules_v4/cronjob/cli/smoke-job.php`, klicken Sie **Jetzt ausführen**, warten Sie eine Minute — die Verlauf-Seite sollte eine grüne `ok`-Zeile zeigen.

## Konventionen für Job-Skripte

Neue Job-Skripte in anderen Modulen müssen diese Konventionen einhalten:

- Ort `modules_v4/<module>/cli/`, aufgerufen als `php modules_v4/<module>/cli/<script>.php`
- **Beginnen mit** `require autoload.php` und `CliBootstrap::guard()`
- Idempotent und inkrementell (`--limit`, `--since`), batched
- Exit-Code `0` bei Erfolg
- Keine interaktive Eingabe; alles über CLI-Optionen
- Template-Dateien sind mit `_` Präfix versehen (von der Job-Entdeckung ausgeschlossen)
- Eigene CLI-Skripte können leicht auf folgende Weise begonnen werden:
  - einer **Vorlage:** <a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/_template-maintenance.php" target="_blank" rel="noopener"><code>_template-maintenance.php</code></a>
 – diese in das Verzeichnis `cli/` des eigenen Moduls kopieren, umbenennen und entsprechend anpassen
  - oder, falls das Modul bereits von Cronjobs abhängt, kann dieser Bootstrap-Vorgang stattdessen
    an den gemeinsamen **CLI-Wrapper** delegiert werden

## Wartungsskripte schreiben

### Die Vorlage verwenden

<a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/_template-maintenance.php" target="_blank" rel="noopener"><code>_template-maintenance.php</code></a>
 ist eine Vorlage zum Kopieren und Einfügen für länger laufende Wartungsaufträge. \
Die Konventionen:

- **SAPI-Guard**: Jedes Skript beginnt mit `CliBootstrap::guard()` – das Verzeichnis ist über eine URL erreichbar, der Guard gibt den Status `403` zurück, anstatt das Skript auszuführen.
- **Bootstrap**: Verwende `CliBootstrap::boot()` – die zentrale CLI-Bootstrap-Sequenz (App-Bootstrap, i18n, Konfiguration, Datenbank) mit einem harten Fehler bei fehlender Konfiguration oder fehlender Datenbankverbindung.
- **Argumente**: einfaches `$argv` (`--limit=N`, `--help`).
- **Sperre**: `flock()` auf `data/<module>/<name>.lock`, damit sich überlappende Cron-Läufe nicht kollidieren; eine gehaltene Sperre ist kein Fehler (Beendigungscode 0).
- **Idempotente Batches**: Gestalten Sie den Job so, dass ein Lauf in etwa 5–10 Minuten abgeschlossen ist und der nächste Lauf dort fortgesetzt wird, wo der letzte aufgehört hat.
- **Protokollierung**: einfache Zeilen in der Standardausgabe (Cron-E-Mail / Protokolldatei). Geben Sie niemals personenbezogene Daten aus – Zähler und XREFs, niemals Namen.
- **Exit-Codes**: `0` = ok (einschließlich „nichts zu tun“, „Sperre gehalten“), `1` = Fehler.

### CLI-Wrapper verwenden

Ein Job-Skript, das webtrees + Datenbank braucht, kann den Bootstrap an den gemeinsamen Wrapper des Cronjob-Moduls delegieren:

1. **Payload** `modules_v4/<module>/cli/<name>.logic.php` — die eigentliche Logik.
2. **Stub** `modules_v4/<module>/cli/<name>.php` — worauf die Job-Zeile zeigt:

```php
<?php
declare(strict_types=1);
$wrapper = __DIR__ . '/../../cronjob/cli/wrap.php';
if (is_file($wrapper)) {
    require $wrapper;
} else {
    fwrite(STDERR, "cronjob module required for this job\n");
    exit(1);
}
```

<a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/wrap.php" target="_blank" rel="noopener"><code>wrap.php</code></a>
 bootstrapt webtrees + DB und inkludiert dann das Payload (Geschwisterdatei mit `.logic.php`-Erweiterung). Der Payload-Pfad wird aus dem Entry-Skript abgeleitet, nie aus einem Argument genommen.
