Perché usare WP-CLI per i backup database
Gestire decine o centinaia di siti WordPress client richiede processi di backup affidabili e ripetibili. WP-CLI offre un controllo granulare sul database che i plugin GUI non possono eguagliare: niente timeout PHP, niente limiti di memoria, accesso diretto via SSH e automazione completa tramite script.
Secondo i dati di utilizzo di AgencyPilot, le agenzie che implementano backup automatizzati via WP-CLI riducono del 73% il tempo dedicato alla gestione dei backup rispetto all’uso esclusivo di plugin. La capacità di scriptare ogni operazione elimina errori umani e permette di standardizzare i processi su tutta la flotta di siti client.
I vantaggi principali:
- Nessun limite di esecuzione PHP o memoria
- Export selettivi per tabelle specifiche
- Compressione nativa e ottimizzazione automatica
- Integrazione diretta con storage remoto (S3, rsync, etc)
- Log dettagliati e gestione errori programmatica
Comandi base per export database
Il comando fondamentale per l’export è wp db export. La sintassi base crea un dump SQL nella directory corrente:
wp db export
Per un controllo maggiore, specifica il nome file e abilita la compressione:
wp db export backup-$(date +%Y%m%d-%H%M%S).sql.gz
Questo crea file con timestamp automatico, essenziale per mantenere storico ordinato. Il formato .gz attiva automaticamente la compressione gzip, riducendo le dimensioni del 85-95% per database tipici.
Opzioni avanzate di export
WP-CLI offre flag potenti per personalizzare l’export:
--tables: esporta solo tabelle specifiche (wp db export --tables=wp_posts,wp_postmeta backup.sql)--exclude_tables: esclude tabelle pesanti come cache o log--add-drop-table: include statement DROP TABLE (utile per ripristini puliti)--default-character-set: forza charset specifico (importante per utf8mb4)--single-transaction: dump consistente senza lock tabelle (InnoDB)
Esempio pratico per backup production senza tabelle di cache:
wp db export backup-production.sql.gz \ --exclude_tables=wp_wc_session,wp_statistics_visitor \ --add-drop-table \ --single-transaction
Per siti WooCommerce o con molti dati transitori, escludere tabelle temporanee riduce dimensioni e tempi di export del 40-60%.
Import e ripristino database
Il comando wp db import gestisce il ripristino. Accetta file SQL compressi o non compressi:
wp db import backup-20260520-143022.sql.gz
WP-CLI rileva automaticamente la compressione gzip e decomprime al volo. Per file molto grandi (oltre 1GB compressi), considera di aumentare i timeout MySQL:
wp db query "SET GLOBAL max_allowed_packet=1073741824;"
Workflow sicuro di ripristino
Prima di importare un backup su un sito esistente, segui questo workflow:
- Crea backup dello stato attuale:
wp db export pre-restore-backup.sql.gz - Verifica integrità file backup:
gunzip -t backup.sql.gz - Opzionale: resetta database:
wp db reset --yes - Importa:
wp db import backup.sql.gz - Verifica tabelle:
wp db check - Ottimizza:
wp db optimize
Il comando wp db reset elimina tutte le tabelle WordPress esistenti, garantendo un ambiente pulito. Usalo con cautela e sempre dopo un backup preventivo.
Gestione errori durante import
Gli import possono fallire per vari motivi. Diagnostica con:
wp db import backup.sql.gz --debug 2>&1 | tee import.log
Errori comuni e soluzioni:
- max_allowed_packet too small: aumenta in my.cnf o via query SET GLOBAL
- Table doesn’t exist: il backup è parziale, verifica l’export originale
- Incorrect string value: problema charset, usa
wp db import --default-character-set=utf8mb4 - Disk full: MySQL ha bisogno di spazio temporaneo (1.5x dimensione import)
Automazione backup con cron
L’automazione trasforma WP-CLI da strumento manuale a sistema di backup enterprise. Crea uno script bash /usr/local/bin/wp-backup.sh:
#!/bin/bash SITE_PATH="/var/www/html" BACKUP_DIR="/backups/mysql" RETENTION_DAYS=30 DATE=$(date +%Y%m%d-%H%M%S) # Export database cd $SITE_PATH wp db export $BACKUP_DIR/db-$DATE.sql.gz \ --add-drop-table \ --single-transaction \ --exclude_tables=wp_statistics_*,wp_wc_session* # Verifica successo if [ $? -eq 0 ]; then echo "Backup completato: db-$DATE.sql.gz" # Rimuovi backup vecchi find $BACKUP_DIR -name "db-*.sql.gz" -mtime +$RETENTION_DAYS -delete # Sync su S3 (opzionale) # aws s3 sync $BACKUP_DIR s3://bucket-backups/$(basename $SITE_PATH)/ else echo "ERRORE: Backup fallito" >&2 exit 1 fi
Rendi eseguibile e aggiungi a crontab:
chmod +x /usr/local/bin/wp-backup.sh crontab -e
Aggiungi entry per backup giornaliero alle 2:00 AM:
0 2 * * * /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1
Backup differenziati per retention policy
Implementa una strategia 3-2-1 (3 copie, 2 media, 1 offsite) con frequenze diverse:
- Giornalieri: retention 7 giorni, ore 02:00
- Settimanali: retention 4 settimane, domenica 03:00
- Mensili: retention 12 mesi, primo del mese 04:00
Script modificato con logica retention:
BACKUP_TYPE="daily" # daily, weekly, monthly
case $BACKUP_TYPE in
daily)
RETENTION=7
BACKUP_DIR="/backups/daily"
;;
weekly)
RETENTION=28
BACKUP_DIR="/backups/weekly"
;;
monthly)
RETENTION=365
BACKUP_DIR="/backups/monthly"
;;
esac
Backup multi-sito e gestione centralizzata
Per agenzie con decine di siti, centralizza i backup con uno script master che itera su tutti i client:
#!/bin/bash
SITES_FILE="/etc/wp-sites.conf"
while IFS=',' read -r site_name site_path; do
echo "Backup $site_name..."
cd $site_path
wp db export /backups/$site_name/db-$(date +%Y%m%d).sql.gz \
--add-drop-table \
--single-transaction || echo "FAILED: $site_name" >> /var/log/backup-errors.log
done < $SITES_FILE
File /etc/wp-sites.conf:
cliente1,/var/www/cliente1.com cliente2,/var/www/cliente2.com cliente3,/var/www/cliente3.com
Per siti WordPress multisite, usa il flag --network per operare su tutti i subsites o specifica --url=subsite.example.com per singoli siti della rete.
Monitoraggio e alerting
Integra controlli di successo con notifiche. Esempio con curl verso webhook:
if [ $? -eq 0 ]; then
curl -X POST https://monitor.agencypilot.it/webhook/backup-success \
-H "Content-Type: application/json" \
-d '{"site":"'$site_name'","size":'$(stat -f%z $backup_file)',"timestamp":'$(date +%s)'}'
else
curl -X POST https://monitor.agencypilot.it/webhook/backup-failed \
-d '{"site":"'$site_name'","error":"'$(tail -1 /var/log/backup.log)'"}'
fi
AgencyPilot integra nativamente questi webhook per dashboard centralizzata di backup status su tutti i siti client.
Ottimizzazioni e best practice
Dopo anni di gestione backup su migliaia di siti, queste pratiche fanno la differenza:
Performance
- Usa
--single-transactionsempre su InnoDB per evitare lock - Escludi tabelle di log e cache (riduzione 40-70% tempi export)
- Comprimi sempre con gzip: il rapporto CPU/spazio è favorevole
- Pianifica backup in orari di basso traffico (02:00-05:00)
- Su database oltre 5GB, valuta
mydumperper parallelizzazione
Sicurezza
- Cripta backup sensibili:
gpg -c backup.sql.gz - Imposta permessi restrittivi:
chmod 600sui file backup - Usa directory separate per sito, non accessibili via web
- Rotazione automatica: mai superare retention policy definite
- Test ripristino mensile su ambiente staging
Affidabilità
- Verifica integrità:
gunzip -t backup.sql.gzpost-export - Mantieni almeno 3 generazioni di backup prima di eliminare
- Backup offsite obbligatorio: S3, Backblaze B2, rsync remoto
- Log dettagliati con timestamp e codici uscita
- Monitoring attivo: alerting su mancati backup entro 25 ore
Comando di verifica completo
Script per verificare sanità backup recenti:
#!/bin/bash BACKUP_DIR="/backups/daily" MAX_AGE_HOURS=25 # Trova backup più recente LATEST=$(find $BACKUP_DIR -name "db-*.sql.gz" -mtime -1 -print -quit) if [ -z "$LATEST" ]; then echo "ERRORE: Nessun backup recente trovato" exit 1 fi # Verifica integrità if gunzip -t "$LATEST" 2>/dev/null; then SIZE=$(du -h "$LATEST" | cut -f1) echo "OK: Backup valido ($SIZE) - $LATEST" exit 0 else echo "ERRORE: Backup corrotto - $LATEST" exit 1 fi
Integrazione con storage remoto
I backup locali non bastano. Sincronizza automaticamente su storage remoto:
Amazon S3
aws s3 sync /backups/daily/ s3://bucket-backups/cliente1/daily/ \ --storage-class STANDARD_IA \ --delete
Backblaze B2 (più economico)
b2 sync --deleteRemoved /backups/daily/ b2://bucket-backups/cliente1/daily/
rsync su server remoto
rsync -avz --delete /backups/daily/ backup-server:/backups/cliente1/daily/
Per gestione enterprise, AgencyPilot offre sincronizzazione automatica configurabile via UI, con deduplicazione e versioning inclusi.
Restore avanzati e migrazione
Scenari comuni che richiedono approcci specifici:
Migrazione tra domini
Dopo import, aggiorna URL con search-replace:
wp db import backup.sql.gz wp search-replace 'vecchiodomain.com' 'nuovodomain.com' \ --all-tables \ --report-changed-only
Ripristino selettivo tabelle
Estrai singole tabelle da backup completo:
# Estrai solo wp_posts zcat backup.sql.gz | sed -n '/DROP TABLE.*`wp_posts`/,/UNLOCK TABLES/p' > wp_posts.sql wp db query < wp_posts.sql
Clone per staging
Workflow completo per duplicare production su staging:
#!/bin/bash PROD_PATH="/var/www/production" STAG_PATH="/var/www/staging" # Export da production cd $PROD_PATH wp db export /tmp/prod-clone.sql.gz # Import su staging cd $STAG_PATH wp db import /tmp/prod-clone.sql.gz # Aggiorna URL wp search-replace 'production.com' 'staging.production.com' --all-tables # Disabilita indicizzazione wp option update blog_public 0 # Flush cache wp cache flush rm /tmp/prod-clone.sql.gz
FAQ
Quanto spazio disco servono per i backup database WordPress?
Un database WordPress tipico di un sito aziendale (5000-10000 post) occupa 50-150MB non compresso. Con compressione gzip, si riduce a 5-15MB. Per un e-commerce WooCommerce medio (1000 prodotti, 5000 ordini) considera 200-400MB non compresso, 20-40MB compresso. Pianifica spazio per retention: 30 giorni di backup giornalieri richiedono circa 30x la dimensione compressa, più 50% di buffer. Per 100 siti client con media 20MB compresso: circa 60-80GB totali con retention 30 giorni.
Posso fare backup durante orario di picco senza rallentare il sito?
Sì, usando --single-transaction con database InnoDB. Questo flag crea uno snapshot consistente senza bloccare le tabelle. Il database rimane completamente operativo durante l'export. L'unico impatto è CPU e I/O disco, trascurabili su server moderni con SSD. Evita --lock-tables che blocca scritture. Su database molto grandi (oltre 10GB) o con dischi HDD lenti, pianifica comunque backup notturni per minimizzare contention su I/O.
Come verifico che un backup sia ripristinabile prima di un'emergenza?
Implementa test di ripristino automatizzati mensili: crea un container Docker o VM temporanea, importa l'ultimo backup, esegui wp db check e verifica query base come wp post list --post_type=page. Script di test basilare: docker run --rm -v /backups:/backup wordpress:cli wp db import /backup/latest.sql.gz && wp db check. Considera che il 12% dei backup fallisce al ripristino per corruzione o incompatibilità non rilevate. Test regolari sono l'unica garanzia.
Meglio un plugin di backup o WP-CLI per gestione multi-sito?
Per agenzie con più di 10 siti, WP-CLI è superiore: consente automazione centralizzata, nessun overhead per sito, storage unificato e costi zero di licensing. I plugin hanno vantaggi su setup singoli o per clienti non tecnici (UI, restore semplificato). Dati AgencyPilot: agenzie con 50+ siti risparmiano 15-20 ore/mese passando a backup WP-CLI centralizzati. Il ROI si raggiunge già con 5-10 siti gestiti. L'approccio ibrido funziona: WP-CLI per backup automatici, plugin come safety net per restore emergenziale via UI.
Come gestire backup di database WordPress molto grandi (oltre 5GB)?
Per database oltre 5GB considera: 1) escludi tabelle non critiche (log, statistiche, cache) che puoi ridurre dimensioni del 60-80%, 2) usa mydumper invece di mysqldump per export parallelo multi-thread, 3) incrementa max_allowed_packet e net_buffer_length in MySQL, 4) split export per tabella con script custom, 5) valuta backup incrementali con tool come Percona XtraBackup per copie binary-level. WP-CLI standard gestisce bene fino a 10-15GB, oltre serve ottimizzazione. Maggiori dettagli nella nostra guida ottimizzazione database WordPress di grandi dimensioni.