Quando si gestisce un sito, può rendersi necessario spostarlo o sincronizzarlo da un server a un altro. Ad esempio, si potrebbe voler replicare il sito in un ambiente di staging o trasferirlo su un nuovo hosting. In questo articolo, vedremo uno script bash che automatizza questo processo.

Introduzione

Lo script che presento qui permette di sincronizzare un sito da un server sorgente (SOURCE) a un server di destinazione (DESTINATION); effettua una copia dei file del sito e del database MySQL/Mariadb, sostituisce l'URL del sito nel dump del database e lo importa sul server di destinazione. Lo esamineremo passo dopo passo per poi vedere il codice completo.

Configurazione dello Script

Per utilizzare lo script, è necessario configurare alcune variabili che definiscono i percorsi e le credenziali sia del sito sorgente che di quello di destinazione.

In questo esempio si considera un sito WordPress, ma lo script può essere adattato per qualsiasi tipo di sito.

Ecco la sezione di configurazione:

# Configurazione
SOURCE_PATH="/var/www/source.domain.com/wordpress"
SOURCE_DB_NAME="db_source_domain_name"
SOURCE_URL="source.domain.com"

DESTINATION_USER="nome_utente"
DESTINATION_HOST="192.168.0.6"
DESTINATION_PATH="/var/www/destination.domain.com/wordpress"
DESTINATION_DB_NAME="db_destination_domain_name"
DESTINATION_URL="destination.domain.com"
  • SOURCE_PATH: Percorso completo della cartella del sito sorgente.
  • SOURCE_DB_NAME: Nome del database MySQL del sito sorgente.
  • SOURCE_URL: URL del sito sorgente (senza http:// o https://).
  • DESTINATION_USER: Nome utente per accedere al server di destinazione via SSH.
  • DESTINATION_HOST: Indirizzo IP o nome del server di destinazione.
  • DESTINATION_PATH: Percorso completo della cartella del sito di destinazione.
  • DESTINATION_DB_NAME: Nome del database MySQL del sito di destinazione.
  • DESTINATION_URL: URL del sito di destinazione (senza http:// o https://).

Come Funziona lo Script

1. Gestione degli Errori

Lo script include una funzione handle_error che gestisce eventuali errori durante l'esecuzione. Se uno dei comandi restituisce un errore, la funzione viene chiamata e lo script termina pulendo eventuali file temporanei creati.

function handle_error {
    echo "Errore su riga $1"
    rm -f /tmp/${SOURCE_DB_NAME}.sql
    ssh "${DESTINATION_USER}@${DESTINATION_HOST}" "rm -f /tmp/${DESTINATION_DB_NAME}.sql"
    exit 1
}

trap 'handle_error $LINENO' ERR
  • trap: Comando per impostare un'azione da eseguire quando si verifica un errore.

2. Verifica delle Dipendenze

Prima di iniziare la sincronizzazione, lo script verifica che i comandi essenziali (ssh, rsync, mysqldump, sed, scp, mysql) siano installati sulla macchina di origine.

for cmd in ssh rsync mysqldump sed scp mysql; do
    if ! command -v $cmd &> /dev/null; then
        echo "Errore: il comando '$cmd' non è installato." >&2
        exit 1
    fi
done

3. Richiesta di Conferma

Lo script informa l'utente su cosa farà e chiede conferma per procedere.

echo "Questo script sincronizza un sito web da un server SOURCE a un server DESTINATION."
read -p "Vuoi continuare? (s/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Ss]$ ]]; then
    echo "Operazione annullata."
    exit 1
fi

4. Sincronizzazione dei File

Utilizzando rsync, lo script copia tutti i file dal percorso del sito sorgente a quello di destinazione, escludendo eventuali cartelle di cache.

rsync -avz --delete --no-times --no-perms --exclude 'cache/' "${SOURCE_PATH}/" "${DESTINATION_USER}@${DESTINATION_HOST}:${DESTINATION_PATH}/"
  • -a: Opzione per copiare i file in modalità archivio, mantenendo i permessi, le proprietà e i timestamp.
  • -v: Opzione per visualizzare l'output dettagliato.
  • -z: Opzione per comprimere i dati durante il trasferimento.
  • --delete: Opzione per eliminare i file sul server di destinazione che non esistono più sul server sorgente.
  • --no-times: Opzione per non copiare i timestamp dei file.
  • --no-perms: Opzione per non copiare i permessi dei file.
  • --exclude 'cache/': Opzione per escludere la cartella cache/ dal trasferimento.

5. Dump e Modifica del Database

Lo script esegue il dump del database MySQL sul server sorgente, sostituisce l'URL del sito sorgente con quello di destinazione e trasferisce il dump al server di destinazione.

mysqldump -u root -p"${SOURCE_DB_PASS}" "${SOURCE_DB_NAME}" > "/tmp/${SOURCE_DB_NAME}.sql"
sed -i "s|${SOURCE_URL}|${DESTINATION_URL}|g" "/tmp/${SOURCE_DB_NAME}.sql"
scp "/tmp/${SOURCE_DB_NAME}.sql" "${DESTINATION_USER}@${DESTINATION_HOST}:/tmp/${DESTINATION_DB_NAME}.sql"
  • mysqldump: Comando per eseguire il dump del database MySQL.
  • sed: Comando per sostituire il nome del sito nel dump del database.
  • scp: Comando per copiare il dump del database modificato dal server sorgente a quello di destinazione.

6. Importazione del Database

Infine, il database viene importato sul server di destinazione e vengono eliminati i file temporanei.

ssh "${DESTINATION_USER}@${DESTINATION_HOST}" "mysql -u root -p'${DESTINATION_DB_PASS}' ${DESTINATION_DB_NAME} < /tmp/${DESTINATION_DB_NAME}.sql"

Script Completo

#!/bin/bash

# LO SCRIPT DEVE ESSERE ESEGUITO SUL SERVER "SOURCE"

# ========================================
# Configurazione
# Modifica i valori delle variabili con i tuoi dati
# ATTENZIONE: gli URL devono essere inseriti senza http:// o https:// e senza slash finale, es. "example.com"
# ========================================
SOURCE_PATH="/var/www/source.domain.com/wordpress"
SOURCE_DB_NAME="db_source_domain_name"
SOURCE_URL="source.domain.com"
DESTINATION_USER="nome_utente"
DESTINATION_HOST="192.168.0.6"
DESTINATION_PATH="/var/www/destination.domain.com/wordpress"
DESTINATION_DB_NAME="db_destination_domain_name"
DESTINATION_URL="destination.domain.com"
# ========================================

# Funzione per la gestione degli errori
function handle_error {
    echo "Errore su riga $1"
    # Pulizia in caso di errore
    rm -f /tmp/${SOURCE_DB_NAME}.sql
    ssh "${DESTINATION_USER}@${DESTINATION_HOST}" "rm -f /tmp/${DESTINATION_DB_NAME}.sql"
    exit 1
}

# Imposta il trap per gestire gli errori
trap 'handle_error $LINENO' ERR

# Verifica le dipendenze
for cmd in ssh rsync mysqldump sed scp mysql; do
    if ! command -v $cmd &> /dev/null; then
        echo "Errore: il comando '$cmd' non è installato." >&2
        exit 1
    fi
done

# Spiega cosa fa lo script e chiedi all'utente se vuole continuare o meno
echo "Questo script sincronizza un sito web da un server SOURCE a un server DESTINATION."
echo "Il sito web sarà copiato da SOURCE a DESTINATION e il database sarà esportato da SOURCE, modificato e importato su DESTINATION."
read -p "Vuoi continuare? (s/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Ss]$ ]]; then
    echo "Operazione annullata."
    exit 1
fi

# Chiede la password del database di SOURCE e DESTINATION
read -s -p "Inserisci la password del database di SOURCE: " SOURCE_DB_PASS
echo
read -s -p "Inserisci la password del database di DESTINATION: " DESTINATION_DB_PASS
echo

# Controllo che le password non siano vuote
if [[ -z "${SOURCE_DB_PASS}" || -z "${DESTINATION_DB_PASS}" ]]; then
    echo "Errore: una o entrambe le password sono vuote."
    exit 1
fi

# Controllo la connessione al server DESTINATION
echo "Controllo la connessione al server DESTINATION..."
if ! ssh -q "${DESTINATION_USER}@${DESTINATION_HOST}" exit; then
    echo "Impossibile connettersi al server DESTINATION!"
    exit 1
fi

# Copia i file dal server SOURCE al server DESTINATION
echo "Copia dei file da SOURCE a DESTINATION..."
rsync -avz --delete --no-times --no-perms --exclude 'cache/' "${SOURCE_PATH}/" "${DESTINATION_USER}@${DESTINATION_HOST}:${DESTINATION_PATH}/"

# Dump del database su SOURCE
echo "Eseguo il dump del database su SOURCE..."
mysqldump -u root -p"${SOURCE_DB_PASS}" "${SOURCE_DB_NAME}" > "/tmp/${SOURCE_DB_NAME}.sql"

# Sostituisci il nome del sito nel dump del database
echo "Sostituisco il nome del sito nel dump del database..."
sed -i "s|${SOURCE_URL}|${DESTINATION_URL}|g" "/tmp/${SOURCE_DB_NAME}.sql"

# Copia del dump del database modificato da SOURCE a DESTINATION
echo "Copia del dump del database modificato da SOURCE a DESTINATION..."
scp "/tmp/${SOURCE_DB_NAME}.sql" "${DESTINATION_USER}@${DESTINATION_HOST}:/tmp/${DESTINATION_DB_NAME}.sql"

# Importa il database su DESTINATION
echo "Importo il database su DESTINATION..."
ssh "${DESTINATION_USER}@${DESTINATION_HOST}" "mysql -u root -p'${DESTINATION_DB_PASS}' ${DESTINATION_DB_NAME} < /tmp/${DESTINATION_DB_NAME}.sql"

# Rimuovi i file temporanei
echo "Pulizia dei file temporanei..."
rm -f "/tmp/${SOURCE_DB_NAME}.sql"
ssh "${DESTINATION_USER}@${DESTINATION_HOST}" "rm -f /tmp/${DESTINATION_DB_NAME}.sql"

echo "Sincronizzazione completata!"

Esecuzione dello Script

Per eseguire lo script, è necessario salvare il codice in un file .sh, ad esempio sync_wordpress.sh, e renderlo eseguibile:

chmod +x sync_wordpress.sh
./sync_wordpress.sh

Considerazioni Finali

Per ulteriori necessità di personalizzazione, lo script può essere facilmente adattato per includere altre funzionalità o per gestire scenari più complessi e ricorda che è sempre consigliabile eseguire un backup completo del sito prima di eseguire operazioni di sincronizzazione o migrazione.