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)
|
## 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).
|
- **`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
|
### 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
|
```bash
|
||||||
./scripts/analyse-nextcloud.sh # Konfiguration, DNS, Verbindungsversuch
|
./scripts/analyse-nextcloud.sh # Konfiguration, DNS, Verbindungsversuch
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,16 @@
|
||||||
# Schlägt der fehl, grenzt das Script die Ursache über Gegenproben ein:
|
# Schlägt der fehl, grenzt das Script die Ursache über Gegenproben ein:
|
||||||
# ohne IP-Pinning, nur IPv4, nur IPv6.
|
# 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.
|
# Rein lesend – es werden keine Belege importiert, verschoben oder gelöscht.
|
||||||
# Das Passwort wird nie im Klartext ausgegeben.
|
# Das Passwort wird nie im Klartext ausgegeben.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ./analyse-nextcloud.sh [--verbose]
|
# ./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
|
set -euo pipefail
|
||||||
|
|
@ -145,6 +148,42 @@ function isOk(array $r): bool
|
||||||
return $r['errno'] === 0 && $r['code'] >= 200 && $r['code'] < 300;
|
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 ────────────────────────────────────────────────────────
|
// ── 1. Konfiguration ────────────────────────────────────────────────────────
|
||||||
$section('1. Konfiguration (Einstellungen → Nextcloud-Belegimport)');
|
$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;
|
echo ' Netzwerkverbindung, Firewall und TLS-Zertifikat der Nextcloud prüfen.' . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$checkImportScript();
|
||||||
exit(1);
|
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;
|
echo PHP_EOL . ' ' . $green('Die Verbindung zur Nextcloud funktioniert.') . PHP_EOL . PHP_EOL;
|
||||||
exit(0);
|
exit(0);
|
||||||
PHPEOF
|
PHPEOF
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,21 @@ class AnalyseNextcloudSkriptTest extends TestCase
|
||||||
// Verweise auf NextcloudImportService im Kommentar sind erwünscht (die cURL-Optionen
|
// Verweise auf NextcloudImportService im Kommentar sind erwünscht (die cURL-Optionen
|
||||||
// müssen dort synchron gehalten werden) – ausgeführt werden darf der Import nicht.
|
// müssen dort synchron gehalten werden) – ausgeführt werden darf der Import nicht.
|
||||||
$this->assert(
|
$this->assert(
|
||||||
!str_contains($content, 'nextcloud-import.php') && !str_contains($content, 'new NextcloudImportService'),
|
!str_contains($content, 'new NextcloudImportService'),
|
||||||
'Skript startet keinen Importlauf'
|
'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
|
// Das Passwort dient ausschließlich als cURL-Zugangsdatum. In Ausgaben darf
|
||||||
// es nur als Länge (strlen) auftauchen, nie im Klartext.
|
// es nur als Länge (strlen) auftauchen, nie im Klartext.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue