Fix #209: analyse-nextcloud.sh prüft, ob das Importskript vorhanden und ladbar ist
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
69fcc84301
commit
b7508fe401
4 changed files with 67 additions and 3 deletions
|
|
@ -2,6 +2,11 @@
|
|||
|
||||
---
|
||||
|
||||
## 2026-09-20 – Analyse prüft das Importskript (#209)
|
||||
|
||||
- **`scripts/analyse-nextcloud.sh`:** neuer Abschnitt 6 prüft, ob `scripts/container/nextcloud-import.php` im Container existiert und syntaktisch ladbar ist (`php -l`, ohne Ausführung), und nennt den Pfad, den der Host-Cronjob verwenden muss. Fehlt das Skript, endet die Analyse mit Exit 1 – auch bei erfolgreicher Verbindung. Ein `--dry-run`-Schalter für den Import wurde nicht ergänzt.
|
||||
- **`tests/75_AnalyseNextcloudSkriptTest.php`:** prüft die Existenzabfrage und dass das Importskript nie ausgeführt wird.
|
||||
|
||||
## 2026-09-20 – Überwachung des Nextcloud-Imports (#208)
|
||||
|
||||
- **`migrations/096_nextcloud_watchdog.sql`** (neu): `company_settings.nextcloud_last_run` (Zeitstempel des letzten Laufs) und `nextcloud_alarm_stunden` (Schwelle, Default 24, 0 = aus).
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ sudo usermod -aG docker $USER
|
|||
|
||||
### Verbindung analysieren
|
||||
|
||||
Meldet der Import „PROPFIND fehlgeschlagen" oder findet er keine Dateien, grenzt `scripts/analyse-nextcloud.sh` die Ursache ein. Das Skript wird auf dem Host aufgerufen (nicht im Container) und arbeitet rein lesend – es importiert, verschiebt und löscht nichts. Das Passwort wird nie im Klartext ausgegeben.
|
||||
Meldet der Import „PROPFIND fehlgeschlagen" oder findet er keine Dateien, grenzt `scripts/analyse-nextcloud.sh` die Ursache ein. Das Skript wird auf dem Host aufgerufen (nicht im Container) und arbeitet rein lesend – es importiert, verschiebt und löscht nichts. Das Passwort wird nie im Klartext ausgegeben. Zum Schluss prüft die Analyse, ob `scripts/container/nextcloud-import.php` im Container vorhanden und ladbar ist (ohne es auszuführen), und nennt den Pfad, den der Host-Cronjob verwenden muss.
|
||||
|
||||
```bash
|
||||
./scripts/analyse-nextcloud.sh # Konfiguration, DNS, Verbindungsversuch
|
||||
|
|
|
|||
|
|
@ -7,13 +7,16 @@
|
|||
# Schlägt der fehl, grenzt das Script die Ursache über Gegenproben ein:
|
||||
# ohne IP-Pinning, nur IPv4, nur IPv6.
|
||||
#
|
||||
# Zuletzt wird geprüft, ob das Importskript im Container existiert und ladbar
|
||||
# ist (der Cronjob muss denselben Pfad verwenden).
|
||||
#
|
||||
# Rein lesend – es werden keine Belege importiert, verschoben oder gelöscht.
|
||||
# Das Passwort wird nie im Klartext ausgegeben.
|
||||
#
|
||||
# Usage:
|
||||
# ./analyse-nextcloud.sh [--verbose]
|
||||
#
|
||||
# Exit-Code: 0 = Verbindung steht, 1 = Konfigurations- oder Verbindungsfehler
|
||||
# Exit-Code: 0 = Verbindung steht und Importskript vorhanden, 1 = Konfigurations- oder Verbindungsfehler
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
set -euo pipefail
|
||||
|
|
@ -145,6 +148,42 @@ function isOk(array $r): bool
|
|||
return $r['errno'] === 0 && $r['code'] >= 200 && $r['code'] < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob der Importlauf selbst startbar ist. Die Analyse läuft über die
|
||||
* Standardeingabe und braucht das Importskript nicht – ein verschobenes oder
|
||||
* fehlendes Skript bliebe sonst unbemerkt, obwohl der Cronjob ins Leere läuft.
|
||||
* Das Skript wird nur auf Syntax geprüft (php -l), nicht ausgeführt.
|
||||
*/
|
||||
$checkImportScript = static function () use ($section, $green, $red, $bold): bool {
|
||||
$section('6. Importskript (Cronjob-Ziel)');
|
||||
|
||||
$rel = 'scripts/container/nextcloud-import.php';
|
||||
$path = '/var/www/html/' . $rel;
|
||||
|
||||
if (!is_file($path)) {
|
||||
echo ' ' . $red('✗') . ' ' . $rel . ' fehlt im Container.' . PHP_EOL;
|
||||
echo ' Der Cronjob findet das Skript nicht und der Import läuft nie.' . PHP_EOL;
|
||||
echo ' Auch prüfen, ob der Bind-Mount ./scripts:/var/www/html/scripts den Image-Inhalt verdeckt.' . PHP_EOL;
|
||||
return false;
|
||||
}
|
||||
|
||||
echo ' ' . $green('✓') . ' ' . $rel . ' vorhanden' . PHP_EOL;
|
||||
|
||||
$output = [];
|
||||
exec(escapeshellarg(PHP_BINARY) . ' -l ' . escapeshellarg($path) . ' 2>&1', $output, $code);
|
||||
if ($code !== 0) {
|
||||
echo ' ' . $red('✗') . ' Das Skript ist nicht ladbar: ' . implode(' ', $output) . PHP_EOL;
|
||||
return false;
|
||||
}
|
||||
echo ' ' . $green('✓') . ' Syntax gültig' . PHP_EOL;
|
||||
|
||||
echo PHP_EOL . ' ' . $bold('Hinweis:') . ' Der Host-Cronjob muss genau diesen Pfad verwenden:' . PHP_EOL;
|
||||
echo ' docker compose exec -T web php ' . $rel . PHP_EOL;
|
||||
echo ' Mit `crontab -l` auf dem Host abgleichen.' . PHP_EOL;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// ── 1. Konfiguration ────────────────────────────────────────────────────────
|
||||
$section('1. Konfiguration (Einstellungen → Nextcloud-Belegimport)');
|
||||
|
||||
|
|
@ -272,6 +311,7 @@ if (!isOk($result)) {
|
|||
echo ' Netzwerkverbindung, Firewall und TLS-Zertifikat der Nextcloud prüfen.' . PHP_EOL;
|
||||
}
|
||||
|
||||
$checkImportScript();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -328,6 +368,13 @@ if ($done !== null) {
|
|||
}
|
||||
}
|
||||
|
||||
$importOk = $checkImportScript();
|
||||
|
||||
if (!$importOk) {
|
||||
echo PHP_EOL . ' ' . $red('Die Verbindung steht, aber der Importlauf ist nicht startbar.') . PHP_EOL . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo PHP_EOL . ' ' . $green('Die Verbindung zur Nextcloud funktioniert.') . PHP_EOL . PHP_EOL;
|
||||
exit(0);
|
||||
PHPEOF
|
||||
|
|
|
|||
|
|
@ -37,9 +37,21 @@ class AnalyseNextcloudSkriptTest extends TestCase
|
|||
// Verweise auf NextcloudImportService im Kommentar sind erwünscht (die cURL-Optionen
|
||||
// müssen dort synchron gehalten werden) – ausgeführt werden darf der Import nicht.
|
||||
$this->assert(
|
||||
!str_contains($content, 'nextcloud-import.php') && !str_contains($content, 'new NextcloudImportService'),
|
||||
!str_contains($content, 'new NextcloudImportService'),
|
||||
'Skript startet keinen Importlauf'
|
||||
);
|
||||
// Das Importskript wird nie ausgeführt – nur per Syntaxprüfung (php -l) angefasst.
|
||||
$this->assert(
|
||||
!preg_match('/\b(passthru|shell_exec|system|proc_open|include|require)\b[^;\n]*nextcloud-import/', $content)
|
||||
&& str_contains($content, "' -l '"),
|
||||
'Skript führt das Importskript nicht aus, sondern prüft nur die Syntax'
|
||||
);
|
||||
|
||||
// Die Analyse muss die Existenz des Importskripts im Container prüfen.
|
||||
$this->assert(
|
||||
str_contains($content, 'scripts/container/nextcloud-import.php') && str_contains($content, 'is_file($path)'),
|
||||
'Skript prüft, ob scripts/container/nextcloud-import.php im Container existiert'
|
||||
);
|
||||
|
||||
// Das Passwort dient ausschließlich als cURL-Zugangsdatum. In Ausgaben darf
|
||||
// es nur als Länge (strlen) auftauchen, nie im Klartext.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue