Update ITA_README_.md
This commit is contained in:
258
ITA_README_.md
Normal file
258
ITA_README_.md
Normal file
@@ -0,0 +1,258 @@
|
||||
# sld-filebackups-py
|
||||
|
||||
Utility di backup in Python, leggera e senza dipendenze esterne, che archivia file e cartelle dichiarati in un file JSON con rotazione automatica dei backup più vecchi. Pensata per girare come cron job giornaliero su server Linux.
|
||||
|
||||
---
|
||||
|
||||
## Indice
|
||||
|
||||
- [Funzionalità](#funzionalità)
|
||||
- [Struttura del progetto](#struttura-del-progetto)
|
||||
- [Come funziona](#come-funziona)
|
||||
- [Installazione](#installazione)
|
||||
- [Configurazione](#configurazione)
|
||||
- [config.json](#configjson)
|
||||
- [dir_backups.json](#dir_backupsjson)
|
||||
- [Ambiente (init.py)](#ambiente-initpy)
|
||||
- [Utilizzo](#utilizzo)
|
||||
- [Struttura dei backup](#struttura-dei-backup)
|
||||
- [Rotazione automatica](#rotazione-automatica)
|
||||
- [Logging](#logging)
|
||||
- [Esecuzione come cron job](#esecuzione-come-cron-job)
|
||||
- [Requisiti](#requisiti)
|
||||
- [Licenza](#licenza)
|
||||
|
||||
---
|
||||
|
||||
## Funzionalità
|
||||
|
||||
- **Backup selettivo** — definisci i percorsi da salvare in un file JSON, con un flag di abilitazione per ogni voce; non è necessario toccare il codice per aggiungere o rimuovere entry
|
||||
- **Backup di cartelle** — le directory vengono archiviate come `.tar.gz` (solo il nome della cartella viene preservato come radice dell'archivio, nessun percorso assoluto esposto)
|
||||
- **Backup di file singoli** — i file vengono compressi come `.gz`
|
||||
- **Skip automatico se già esiste** — se un backup per la data odierna è già presente, viene saltato; il script può essere lanciato più volte al giorno senza duplicati
|
||||
- **Rotazione automatica** — dopo ogni esecuzione, gli archivi più vecchi oltre una soglia configurabile vengono eliminati per ogni sottocartella
|
||||
- **Modalità dry-run** — anteprima precisa di cosa verrebbe eliminato dalla rotazione, senza cancellare nulla
|
||||
- **Logging strutturato** — output sempre presente su console (utile per leggere l'output di cron); opzionalmente scrive su file di log persistente
|
||||
- **Supporto multi-ambiente** — switch tra configurazioni `local`, `local2` e `prod` in un unico file
|
||||
- **Gestione degli errori robusta** — entry JSON malformate, percorsi mancanti, cartelle vuote ed errori di permessi vengono catturati e loggati senza interrompere l'intera esecuzione
|
||||
|
||||
---
|
||||
|
||||
## Struttura del progetto
|
||||
```
|
||||
backups_script/
|
||||
├── script.py # Punto di ingresso e parser degli argomenti CLI
|
||||
├── functions.py # Logica principale: backup, rotazione, controlli
|
||||
├── constants.py # Stato condiviso: percorsi, config caricata, timestamp
|
||||
├── logger.py # Setup del logging (console + file handler opzionale)
|
||||
├── init.py # Selettore di ambiente (local / prod)
|
||||
├── config.json # Configurazione runtime
|
||||
├── dir_backups.json # Lista dichiarativa dei percorsi da salvare
|
||||
└── LICENSE # GNU GPL v3
|
||||
```
|
||||
|
||||
### Responsabilità dei moduli
|
||||
|
||||
| File | Ruolo |
|
||||
|---|---|
|
||||
| `init.py` | Definisce `ROOT_DIR_APP` e `ROOT_DIR_BACKUPS` in base all'ambiente selezionato. Importato per primo da tutto il resto. |
|
||||
| `constants.py` | Costruisce tutti i percorsi derivati (cartella backup, percorsi config), carica `config.json` e `dir_backups.json` in memoria, cattura la data odierna e l'ora corrente. |
|
||||
| `logger.py` | Legge `config.json` direttamente e configura il logger root di Python con uno `StreamHandler` (sempre attivo) e un `FileHandler` opzionale. |
|
||||
| `functions.py` | Contiene tutta la logica di business: `default_backup_dir()`, `check_existing_folders()`, `backups_now()`, `autorotate_backups()`, `show_enabled()`. |
|
||||
| `script.py` | Inizializza il logging, poi analizza gli argomenti CLI e chiama la funzione appropriata. Senza flag, esegue backup completo + rotazione. |
|
||||
|
||||
---
|
||||
|
||||
## Come funziona
|
||||
|
||||
1. `script.py` chiama `setup_logger()`, che legge `config.json` e configura il logging.
|
||||
2. `default_backup_dir()` verifica che la cartella di backup root e la sottocartella con il nome host esistano, creandole se necessario.
|
||||
3. `check_existing_folders()` legge `dir_backups.json`, filtra le entry abilitate (`flag == 1`), verifica che ogni percorso esista su disco e lo classifica come `"folder"` o `"file"`. Le directory vuote o non leggibili vengono escluse.
|
||||
4. `backups_now()` itera i percorsi verificati:
|
||||
- Per le **cartelle**: crea un archivio `<nome>_YYYY-MM-DD.tar.gz` tramite il modulo `tarfile`.
|
||||
- Per i **file singoli**: crea una copia compressa `<nome>_YYYY-MM-DD.gz` tramite `gzip` + `shutil.copyfileobj`.
|
||||
- Se l'archivio di oggi esiste già, l'entry viene saltata.
|
||||
5. `autorotate_backups()` scansiona ogni sottocartella diretta della directory di backup dell'host, ordina i file `.gz` per data di modifica (più recenti prima) ed elimina quelli oltre la soglia `keep_backups`.
|
||||
|
||||
---
|
||||
|
||||
## Installazione
|
||||
|
||||
Nessun pacchetto da installare. Il script usa solo la libreria standard di Python.
|
||||
```bash
|
||||
git clone https://gitea.sld-server.org/sld-admin/sld-filebackups-py.git
|
||||
cd sld-filebackups-py
|
||||
```
|
||||
|
||||
Poi imposta il tuo ambiente e i percorsi in `init.py` e `dir_backups.json`.
|
||||
|
||||
---
|
||||
|
||||
## Configurazione
|
||||
|
||||
### `config.json`
|
||||
```json
|
||||
{
|
||||
"keep_backups": 7,
|
||||
"logs": false,
|
||||
"logs_path": "/home/backups/logs"
|
||||
}
|
||||
```
|
||||
|
||||
| Chiave | Tipo | Default | Descrizione |
|
||||
|---|---|---|---|
|
||||
| `keep_backups` | intero | `7` | Quanti archivi recenti conservare per sottocartella. I più vecchi vengono eliminati dalla rotazione. |
|
||||
| `logs` | booleano | `false` | Se `true`, viene scritto un file `backup.log` in `logs_path` oltre all'output su console. |
|
||||
| `logs_path` | stringa | `~/backups/logs` | Cartella dove verrà creato `backup.log`. Viene creata automaticamente se non esiste. |
|
||||
|
||||
> **Nota:** Anche quando `logs` è `false`, tutto l'output viene comunque stampato su stdout/stderr, quindi cron lo cattura normalmente tramite mail o redirezione.
|
||||
|
||||
---
|
||||
|
||||
### `dir_backups.json`
|
||||
|
||||
È la lista dichiarativa di tutto ciò che deve essere salvato. Ogni entry è un array JSON di esattamente tre valori:
|
||||
```json
|
||||
[
|
||||
[ "/percorso/assoluto/cartella", 1, "NomeBackup" ],
|
||||
[ "/percorso/assoluto/file", 1, "BackupConfig" ],
|
||||
[ "/percorso/disabilitato", 0, "VecchiaEntry" ]
|
||||
]
|
||||
```
|
||||
|
||||
| Posizione | Campo | Descrizione |
|
||||
|---|---|---|
|
||||
| 0 | `percorso` | Percorso assoluto del file o della cartella da salvare. |
|
||||
| 1 | `abilitato` | `1` = includi nelle esecuzioni di backup. `0` = salta completamente (la entry viene letta ma mai elaborata). |
|
||||
| 2 | `nome` | Identificativo breve usato come nome della sottocartella nella destinazione del backup e come prefisso del nome dell'archivio. Deve essere unico tra le entry. |
|
||||
|
||||
**Suggerimenti:**
|
||||
- Per disabilitare temporaneamente una entry senza eliminarla, imposta il flag a `0`.
|
||||
- Il campo `nome` diventa una directory dentro `<ROOT_DIR_BACKUPS>/<hostname>/`, quindi evita spazi e caratteri speciali.
|
||||
- Le cartelle vengono salvate solo se non sono vuote e sono leggibili.
|
||||
|
||||
---
|
||||
|
||||
### Ambiente (`init.py`)
|
||||
```python
|
||||
env = "local" # Valori disponibili: "local", "local2", "prod"
|
||||
```
|
||||
|
||||
| Ambiente | `ROOT_DIR_APP` | `ROOT_DIR_BACKUPS` |
|
||||
|---|---|---|
|
||||
| `local` | `/home/sld-admin/Scrivania/backups_script/` | `<ROOT_DIR_APP>/backups/Daily_File_Backups/` |
|
||||
| `local2` | `/home/simo-positive/Desktop/backups_script/` | `<ROOT_DIR_APP>/backups/Daily_File_Backups/` |
|
||||
| `prod` | `/opt/sld-backups/` | `/home/backups/backups_root/Daily_File_Backups/` |
|
||||
|
||||
Se viene impostato un valore sconosciuto, il script termina immediatamente con un errore.
|
||||
|
||||
---
|
||||
|
||||
## Utilizzo
|
||||
```bash
|
||||
# Backup completo + rotazione automatica (comportamento di default, nessun flag richiesto)
|
||||
python3 script.py
|
||||
|
||||
# Mostra quali percorsi sono abilitati e quali disabilitati
|
||||
python3 script.py --show
|
||||
|
||||
# Verifica se i percorsi dichiarati esistono su disco e stampa un report
|
||||
python3 script.py --check
|
||||
|
||||
# Esegui il backup con output di debug verboso
|
||||
python3 script.py --debug
|
||||
|
||||
# Esegui solo la rotazione (nessun nuovo backup creato)
|
||||
python3 script.py --rotate
|
||||
|
||||
# Anteprima di cosa verrebbe eliminato dalla rotazione, senza cancellare nulla
|
||||
python3 script.py --rotate --dry
|
||||
```
|
||||
|
||||
### Riferimento flag CLI
|
||||
|
||||
| Flag | Forma lunga | Descrizione |
|
||||
|---|---|---|
|
||||
| `-s` | `--show` | Stampa i percorsi abilitati e disabilitati da `dir_backups.json`. |
|
||||
| `-d` | `--debug` | Esegue il backup con `debug="on"`, abilitando output verboso sul controllo dei percorsi. |
|
||||
| `-c` | `--check` | Esegue `check_existing_folders()` e stampa lo stato dettagliato per ogni percorso dichiarato. |
|
||||
| `-r` | `--rotate` | Esegue solo `autorotate_backups()`. Può essere combinato con `--dry`. |
|
||||
| | `--dry` | Modalità dry-run per `--rotate`: logga i candidati all'eliminazione ma non cancella nulla. |
|
||||
|
||||
---
|
||||
|
||||
## Struttura dei backup
|
||||
|
||||
I backup vengono scritti sotto:
|
||||
```
|
||||
<ROOT_DIR_BACKUPS>/
|
||||
└── <hostname>/
|
||||
├── Documenti/
|
||||
│ ├── Documenti_2026-03-10.tar.gz
|
||||
│ ├── Documenti_2026-03-11.tar.gz
|
||||
│ └── Documenti_2026-03-12.tar.gz
|
||||
└── BackupConfig/
|
||||
├── BackupConfig_2026-03-10.gz
|
||||
└── BackupConfig_2026-03-11.gz
|
||||
```
|
||||
|
||||
- Ogni entry in `dir_backups.json` ottiene la propria sottocartella con il nome del campo `nome`.
|
||||
- Gli archivi seguono il pattern `<nome>_YYYY-MM-DD.tar.gz` (cartelle) o `<nome>_YYYY-MM-DD.gz` (file).
|
||||
- Il nome host della macchina viene usato come cartella di primo livello, rendendo semplice raccogliere backup di più macchine sotto la stessa root.
|
||||
|
||||
---
|
||||
|
||||
## Rotazione automatica
|
||||
|
||||
La rotazione (`autorotate_backups`) viene eseguita automaticamente dopo ogni backup, oppure può essere avviata manualmente con `--rotate`.
|
||||
|
||||
**Logica:**
|
||||
1. Scansiona ogni sottocartella diretta di `<ROOT_DIR_BACKUPS>/<hostname>/`.
|
||||
2. Trova tutti i file `*.gz` (copre sia `.gz` che `.tar.gz`).
|
||||
3. Li ordina per data di modifica, dal più recente al più vecchio.
|
||||
4. Conserva i primi `keep_backups` (default: 7) ed elimina i restanti.
|
||||
|
||||
**Dry-run** (`--rotate --dry`) logga esattamente quali file verrebbero eliminati, senza nessuna modifica al filesystem. Utile per verificare l'impostazione di retention prima di applicarla.
|
||||
|
||||
---
|
||||
|
||||
## Logging
|
||||
|
||||
Tutte le funzioni usano il modulo standard `logging` di Python tramite un logger con nome (`__name__`). Il logger root viene configurato da `logger.py` all'avvio.
|
||||
|
||||
- **Output su console** sempre attivo (via `StreamHandler`), indipendentemente dall'impostazione `logs`.
|
||||
- **Output su file** aggiunto quando `"logs": true` è impostato in `config.json`. Il file di log è `<logs_path>/backup.log` e viene aggiunto ad ogni esecuzione.
|
||||
- Formato log: `YYYY-MM-DD HH:MM:SS [LIVELLO] messaggio`
|
||||
|
||||
---
|
||||
|
||||
## Esecuzione come cron job
|
||||
|
||||
Per eseguire un backup completo ogni giorno alle 2:00:
|
||||
```bash
|
||||
crontab -e
|
||||
```
|
||||
```
|
||||
0 2 * * * /usr/bin/python3 /opt/sld-backups/script.py >> /home/backups/logs/cron.log 2>&1
|
||||
```
|
||||
|
||||
Poiché il script scrive sempre su stdout, la redirezione dell'output di cron cattura il log completo dell'esecuzione anche se il log su file è disabilitato in `config.json`.
|
||||
|
||||
---
|
||||
|
||||
## Requisiti
|
||||
|
||||
- Python **3.6+**
|
||||
- **Nessun pacchetto di terze parti** — usa solo la libreria standard:
|
||||
- `tarfile`, `gzip`, `shutil` — archiviazione e compressione
|
||||
- `logging` — output strutturato
|
||||
- `argparse` — parsing degli argomenti CLI
|
||||
- `pathlib` — gestione dei percorsi
|
||||
- `socket` — rilevamento del nome host
|
||||
- `json` — caricamento della configurazione
|
||||
|
||||
---
|
||||
|
||||
## Licenza
|
||||
|
||||
GNU General Public License v3.0 — vedi [LICENSE](LICENSE) per i termini completi.
|
||||
Reference in New Issue
Block a user