diff --git a/backup_trilium.sh b/backup_trilium.sh new file mode 100644 index 0000000..f25a2e8 --- /dev/null +++ b/backup_trilium.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# backup_trilium.sh - Backup local horodate de la base Trilium (etage 1). +# Execute en ROOT par le planificateur DSM (le dossier backup/ est en 700 uid 1000). +# 1) demande a Trilium une copie coherente via ETAPI (jamais de copie SQLite a chaud) +# 2) la sort du dossier Docker vers /volume1/backups/trilium, horodatee +# 3) verifie l integrite du fichier copie +# 4) garde les 30 derniers +# Sortie : "OK ..." ou "ERREUR ..." (pour alerte mail DSM). + +BASE=/volume1/homes/Master/App/Context_continuity +PY=$BASE/venv/bin/python3 +SRC=/volume1/docker/trilium/backup/backup-quotidien.db +DEST=/volume1/backups/trilium +URL=http://localhost:4292 +GARDER=30 + +STAMP=$(date +%Y%m%d_%H%M) +CIBLE=$DEST/trilium_$STAMP.db + +TOKEN=$(grep '^TRILIUM_TOKEN=' $BASE/.env | cut -d= -f2- | tr -d '"' | tr -d "'") +if [ -z "$TOKEN" ]; then echo "ERREUR token ETAPI introuvable dans $BASE/.env"; exit 1; fi + +mkdir -p $DEST + +# 1. Demander a Trilium de regenerer la copie (nom dedie : n ecrase pas daily/weekly/monthly) +CODE=$(curl -s -o /dev/null -w "%{http_code}" -X PUT "$URL/etapi/backup/quotidien" -H "Authorization: $TOKEN" --max-time 60) +if [ "$CODE" != "204" ]; then echo "ERREUR ETAPI backup HTTP $CODE"; exit 1; fi + +# 2. Verifier que le fichier existe et vient d etre ecrit, puis le sortir du dossier Docker +if [ ! -f "$SRC" ]; then echo "ERREUR fichier source absent : $SRC"; exit 1; fi +find "$SRC" -mmin -5 | grep -q . || { echo "ERREUR source non regeneree (plus de 5 min)"; exit 1; } +cp "$SRC" "$CIBLE" || { echo "ERREUR copie vers $CIBLE"; exit 1; } + +# 3. Verifier l integrite de la COPIE (un backup non verifie n est pas un backup) +INTEG=$($PY -c "import sqlite3,sys +try: + c=sqlite3.connect('$CIBLE') + r=c.execute('PRAGMA integrity_check').fetchone()[0] + n=c.execute('SELECT count(*) FROM notes').fetchone()[0] + c.close() + print('%s|%d' % (r,n)) +except Exception as e: + print('erreur|%s' % e)") +RESU=$(echo "$INTEG" | cut -d'|' -f1) +NBNOTES=$(echo "$INTEG" | cut -d'|' -f2) +if [ "$RESU" != "ok" ]; then rm -f "$CIBLE"; echo "ERREUR integrite KO ($INTEG) - copie supprimee"; exit 1; fi + +# 4. Rotation : garder les N plus recents +cd $DEST || exit 1 +ls -1t trilium_*.db 2>/dev/null | tail -n +$((GARDER+1)) | while read f; do rm -f "$f"; done + +chmod 600 "$CIBLE" +TAILLE=$(du -h "$CIBLE" | cut -f1) +RESTANT=$(ls -1 trilium_*.db 2>/dev/null | wc -l) +echo "OK $CIBLE ($TAILLE, $NBNOTES notes, $RESTANT backups conserves)"