#!/bin/bash #================================================= # VARIABLES ET HELPERS PROPRES À MABIBLI #================================================= # Nom du binaire produit par `dotnet publish MaBibli.Api`. mabibli_binaire="MaBibli.Api" # Base SQLite. Doit rester cohérent avec `ConnectionStrings__MaBibli` dans # conf/systemd.service. mabibli_base="mabibli.db" # Copie cohérente déposée dans le répertoire de données au moment de la sauvegarde, # puis reprise par le script de restauration. mabibli_instantane="mabibli-instantane.db" #================================================= # SAUVEGARDE À CHAUD DE LA BASE SQLITE #================================================= # # Pourquoi ce n'est pas un simple `cp` : # # La base tourne en mode **WAL** (vérifié sur le publish réel : `PRAGMA journal_mode` # renvoie `wal`, et le répertoire contient bien `mabibli.db-wal` / `mabibli.db-shm`). # En WAL, les écritures récentes vivent dans le fichier `-wal` et **pas** dans le # `.db`. Sur la base fraîchement migrée mesurée en local, le `.db` faisait 4 Ko pour # un `-wal` de 205 Ko : copier le seul `.db` aurait sauvegardé une base à peu près # vide. Copier les trois fichiers pendant que le service écrit ne vaut guère mieux, # puisque rien ne garantit qu'ils soient capturés au même instant. # # `.backup` utilise l'API de sauvegarde en ligne de SQLite : elle produit un fichier # unique, cohérent, sans arrêter le service ni bloquer les lectures. C'est la seule # méthode correcte pour une sauvegarde à chaud, et elle évite d'imposer une coupure # de service à chaque sauvegarde nocturne. # # usage : mabibli_instantane_base "$data_dir" mabibli_instantane_base() { local repertoire="$1" local source="$repertoire/$mabibli_base" local cible="$repertoire/$mabibli_instantane" # Un instantané laissé par une sauvegarde précédente n'a plus de valeur. # (Il ne peut pas être effacé en fin de sauvegarde : `ynh_backup` ne fait que # *déclarer* les chemins, la copie réelle a lieu plus tard, par le cœur de # YunoHost.) rm -f "$cible" if [ ! -f "$source" ]; then ynh_print_warn "Aucune base à $source : rien à figer. Première sauvegarde avant tout démarrage ?" return 0 fi # `.backup` échoue proprement si la base est corrompue : mieux vaut interrompre # la sauvegarde que d'archiver un fichier illisible en croyant être protégé. sqlite3 "$source" ".backup '$cible'" chown "$app:$app" "$cible" chmod 600 "$cible" } #================================================= # REPRISE DE L'INSTANTANÉ APRÈS RESTAURATION #================================================= # # usage : mabibli_reprendre_instantane "$data_dir" mabibli_reprendre_instantane() { local repertoire="$1" local instantane="$repertoire/$mabibli_instantane" if [ ! -f "$instantane" ]; then ynh_print_warn "Pas d'instantané dans l'archive : la base est reprise telle quelle." return 0 fi # ⚠️ Les fichiers `-wal` et `-shm` de l'archive décrivent l'état d'une *autre* # copie de la base. Les laisser à côté de l'instantané ferait rejouer à SQLite # un journal qui ne lui correspond pas. Ils doivent disparaître. rm -f "$repertoire/$mabibli_base" \ "$repertoire/$mabibli_base-wal" \ "$repertoire/$mabibli_base-shm" mv "$instantane" "$repertoire/$mabibli_base" chown "$app:$app" "$repertoire/$mabibli_base" chmod 600 "$repertoire/$mabibli_base" }