---
title: "Avvisi di errore backup: scoprilo prima del ripristino"
description: "I backup falliscono in silenzio per settimane. Intercetta errori di restic e borg, snapshot vecchi ed esecuzioni saltate, e fatti chiamare."
date: 2026-10-09
author: Nooc
authorAvatarLink: /images/avatars/nooc.webp
authorLink: https://nooc.me
tags:
  - monitoraggio backup
  - restic
  - borg
  - avvisi di errore
  - avvisi via chiamata
  - webhook
---

# Avvisi di errore backup: scoprilo prima di dover ripristinare

La maggior parte delle persone scopre che i backup erano rotti il giorno in cui servono. Il job è terminato con un errore tre settimane fa, nessuno ha letto il log, e lo snapshot più recente è più vecchio dell'errore che vuoi annullare.

La soluzione non è uno strumento di backup migliore. È fare in modo che un problema di backup raggiunga una persona nella stessa ora in cui si verifica. Questa guida mostra come farlo per restic e borg (e per qualsiasi cosa si lanci da shell), coprendo i tre modi in cui un backup fallisce davvero, con script da copiare. L'ultimo passo manda l'avviso al telefono tramite [Echobell](/it), così un backup rotto squilla invece di restare in una casella di posta.

## I tre modi in cui un backup fallisce

Monitorare solo il primo è l'errore più comune.

1. **Parte e fallisce.** Repository bloccato, disco pieno, password sbagliata, rete caduta. Lo strumento esce con un codice diverso da zero.
2. **Parte e riesce a metà.** restic esce con il codice `3` quando lo snapshot è stato creato ma alcuni file non erano leggibili. borg esce con `1` per gli avvisi. Entrambi si liquidano facilmente, ed entrambi possono nascondere un problema di permessi che salta in silenzio la tua cartella più importante.
3. **Non parte mai.** Il server era spento, il timer disabilitato, il crontab sovrascritto. Non c'è nessun errore perché non c'è nessun processo. È il guasto che fa più danni.

Ognuno richiede un rilevatore diverso, quindi li costruiremo tutti e tre.

## Passo 1: crea un canale in grado di attirare la tua attenzione

In Echobell crea un canale chiamato `backups` e imposta il tipo di notifica su **Chiamata** per i job che contano. Copia il suo URL del webhook:

```
https://hook.echobell.one/t/<channel-token>
```

Dagli template che abbiano senso anche mezzo addormentati, usando i campi che invieremo qui sotto:

```
Titolo: Backup {{status}} su {{host}}
Corpo: {{job}}: {{detail}}
```

Consulta il [riferimento dei template](/it/docs/template) per la sintassi.

## Passo 2: intercetta gli errori con uno script wrapper

Un piccolo wrapper trasforma i codici di uscita in avvisi. Salvalo come `/usr/local/bin/backup-run`:

```bash
#!/usr/bin/env bash
set -uo pipefail

HOOK="https://hook.echobell.one/t/<channel-token>"
JOB="nightly-restic"

alert() {
  curl -fsS -m 10 -X POST "$HOOK" \
    -H "Content-Type: application/json" \
    -d "{\"job\":\"$JOB\",\"host\":\"$(hostname)\",\"status\":\"$1\",\"detail\":\"$2\"}" || true
}

restic backup /srv /etc --exclude-caches
code=$?

case $code in
  0)  ;;                                   # successo: resta in silenzio
  3)  alert "incomplete" "Snapshot saved, but some files were unreadable" ;;
  11) alert "locked" "Repository is locked by another process" ;;
  12) alert "auth-failed" "Wrong repository password" ;;
  *)  alert "failed" "restic exited with code $code" ;;
esac

exit $code
```

Perché i dettagli contano:

- `set -e` **non** è usato di proposito, così lo script raggiunge comunque l'avviso dopo che restic fallisce.
- `|| true` sul `curl` fa sì che un webhook irraggiungibile non mascheri mai il vero codice di uscita.
- `-m 10` impedisce a una chiamata di rete bloccata di intralciare la prossima esecuzione programmata.

I codici di uscita di restic usati sopra sono documentati nel manuale di restic: `0` successo, `1` errore fatale, `3` snapshot creato ma alcuni file sorgente illeggibili, `10` il repository non esiste, `11` blocco non riuscito, `12` password errata. Verificali con `restic version` sulla tua macchina, perché i codici sono stati aggiunti nel tempo.

### borg e borgmatic

borg restituisce `0` per il successo, `1` per gli avvisi e `2` o più per gli errori. Un file che cambia durante il backup produce `1`, cosa normale per le cartelle di log, quindi un approccio comune è chiamare solo da `2` in su e mandare una notifica silenziosa per `1`:

```bash
borg create --stats ::'{hostname}-{now}' /srv /etc
code=$?
if [ "$code" -ge 2 ]; then
  alert "failed" "borg exited with code $code"
elif [ "$code" -eq 1 ]; then
  alert "warning" "borg finished with warnings"
fi
```

Se usi borgmatic, il suo hook `on_error` esegue un comando quando è borgmatic stesso a incontrare un errore, ed è il posto naturale per lo stesso `curl`. Attenzione al limite che la documentazione di borgmatic dichiara apertamente: se borgmatic non parte mai, `on_error` non scatta mai. È il guasto numero tre, e serve il Passo 3.

## Passo 3: intercetta il backup che non è mai partito

Un wrapper può riferire solo su un'esecuzione avvenuta. Per catturare il silenzio, inverti la logica: il backup invia un ping a un monitor quando **riesce**, e il monitor ti avvisa quando il ping è **in ritardo**. Si chiama dead man's switch.

[Healthchecks.io](https://healthchecks.io) (ospitato o self-hosted) fa esattamente questo:

1. Crea un check con la pianificazione `0 3 * * *` e un tempo di tolleranza di un'ora o due.
2. Aggiungi il suo ping in fondo al job, così parte solo in caso di successo.
3. Nelle integrazioni del check, aggiungi un **Webhook** che punta all'URL del tuo canale Echobell.

Il ping va in fondo al wrapper:

```bash
# in backup-run, subito prima dell'`exit $code` finale; fa il ping solo in caso di successo
if [ $code -eq 0 ]; then
  curl -fsS -m 10 --retry 3 -o /dev/null https://hc-ping.com/<your-uuid>
fi
```

Healthchecks supporta anche le varianti di ping `/start` e `/fail` e può accettare il codice di uscita nell'URL, quindi un solo check può intercettare anche i job che si bloccano. Il risultato: un server spento, un timer disabilitato e una riga di crontab cancellata producono lo stesso esito, un telefono che squilla. Per lo schema generale e altri monitor, vedi [avvisi di errore dei cron job](/it/blog/cron-job-failure-alerts).

## Passo 4: verifica che il backup sia recente e ripristinabile

Un backup può partire in orario, uscire con `0` ed essere comunque inutile, per esempio quando stai salvando una cartella vuota perché un mount è fallito. Aggiungi due controlli di sanità poco costosi in un job giornaliero separato:

**Età dello snapshot.** Avvisa se lo snapshot più recente è più vecchio del previsto:

```bash
latest=$(restic snapshots --latest 1 --json | jq -r '.[0].time')
age_h=$(( ( $(date +%s) - $(date -d "$latest" +%s) ) / 3600 ))
if [ "$age_h" -gt 30 ]; then
  alert "stale" "Newest snapshot is ${age_h}h old"
fi
```

**Integrità del repository.** `restic check` verifica la struttura del repository. Eseguilo ogni settimana; per i repository grandi, `restic check --read-data-subset=5%` campiona i dati senza leggerli tutti. Avvisa su un'uscita diversa da zero.

Nessuno dei due sostituisce un vero ripristino di prova. Una volta a trimestre, ripristina un file verificabile in una cartella temporanea. È l'unico test che dimostra che il backup funziona.

## Passo 5: squilla solo quando conta

Se ogni avviso ti chiama, silenzierai il canale, e poi non squillerà per quello che conta davvero. Usa le [condizioni](/it/docs/conditions) di Echobell per separare i livelli su un solo canale:

```
status == "failed" || status == "stale" || status == "auth-failed"
```

Manda `incomplete` e `warning` a un secondo canale, **Urgente (Time Sensitive)** o normale, così compaiono sulla schermata di blocco senza squillo. Aggiungi una fascia oraria se vuoi che i guasti diurni restino silenziosi, usando le variabili UTC descritte nel riferimento delle condizioni.

## Domande frequenti

### Come vengo avvisato quando un backup fallisce?

Racchiudi il comando di backup in un wrapper, leggi il suo codice di uscita e invia un webhook per qualsiasi codice diverso da zero. Aggiungi un dead man's switch come Healthchecks.io per sapere anche delle esecuzioni mai partite.

### Su quali codici di uscita di restic conviene avvisare?

Avvisa con forza su `1`, `10`, `11` e `12`, che indicano un guasto vero. Tratta `3` (snapshot creato ma alcuni file illeggibili) come un avviso da indagare, perché può nascondere un problema di permessi.

### Come faccio a sapere se un backup ha smesso di girare in silenzio?

Usa un heartbeat: il job invia un ping a un monitor in caso di successo, e il monitor avvisa quando il ping è in ritardo. Un hook di errore non può intercettarlo, perché non gira nulla che possa generare l'errore.

### Un codice di uscita positivo basta per fidarsi di un backup?

No. Significa che lo strumento ha finito, non che i dati siano completi o ripristinabili. Controlla l'età degli snapshot, esegui controlli di integrità periodici e prova regolarmente un ripristino.

### Posso ricevere una telefonata invece di una mail?

Sì. Le mail si perdono facilmente. Un canale di chiamata in Echobell si comporta come una chiamata in arrivo e attraversa la modalità Full Immersion di iOS, quindi un backup fallito alle 03:00 non passa inosservato.

## In sintesi

Tre rilevatori coprono le tre modalità di guasto: un wrapper sui codici di uscita per le esecuzioni che falliscono, un controllo di freschezza per quelle che riescono inutilmente e un heartbeat per quelle che non avvengono mai. Instradali su un canale di chiamata, tieni gli avvisi minori su uno più silenzioso, e un backup rotto diventa una correzione di cinque minuti invece di un weekend perso.

[Scarica Echobell per iPhone](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-backup-failure-alerts-it&mt=8) oppure [prendilo su Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid), crea il canale `backups` ed esegui il wrapper una volta con una password volutamente sbagliata per sentirlo squillare.

## Articoli correlati

- [Avvisi di errore dei cron job](/it/blog/cron-job-failure-alerts)
- [Guida per sviluppatori all'alert fatigue](/it/blog/fix-alert-fatigue-developer-guide)
- [Riferimento delle condizioni di canale](/it/docs/conditions)
- [Guida all'integrazione con i webhook](/it/docs/webhook)
- [Avvisi di scadenza dei certificati SSL](/it/blog/ssl-certificate-expiry-alerts)
