realizzazione
siti web a Bologna

dal 2002
16 anni di siti web

realizzazione avanzata di siti web: gli script bash

16/04/2013

premessa

Questo articolo presuppone un ambiente di lavoro Linux e alcune conoscenze basilari di scripting bash, e illustra come un uso intelligente degli script di shell — attività normalmente associata ai sistemisti — possa essere d'aiuto anche agli sviluppatori. La nostra pratica quotidiana di realizzazione di siti web ci ha insegnato che con questo metodo si possono automatizzare diverse operazioni, con notevole risparmio di tempo e eliminazione degli errori.

Gli script utilizzati come esempio in questo articolo sono versioni ridotte e semplificate di quelli realmente in uso nella nostra web agency e auspichiamo che possano essere una buona base di partenza per chi volesse iniziare a utilizzare degli script bash per semplificare il proprio lavoro di sviluppo.

esempio 1 — backup del sito web via FTP

A volte capita di dover fare un backup dell'intero sito in produzione, per esempio prima di installare aggiornamenti massicci che, anche se ampiamente controllati nell'ambiente di test, possono pur sempre comportare una remota possibilità di avere problemi una volta caricati. In questi casi viene effettuata una serie di operazioni abbastanza semplici, che tuttavia richiedono alcuni passaggi noiosi da eseguire a mano:

  • creazione di una sottocartella del tipo dump.AAAAMMGGHHII all'interno dell'archivio del progetto
  • connessione al server FTP di produzione
  • download dell'intero sito dal server di produzione alla cartella di dump

Se il server di produzione non supporta l'accesso SSH (come spesso accade) non potremo usare rsync (non in maniera semplice, intendo) e dovremo accontentarci di FTP; poco male, come client FTP a linea di comando utilizzeremo ncftp che ha il vantaggio di essere piuttosto leggero oltre che molto semplice da utilizzare. Niente di complicato, come si è detto, ma la comodità di fare tutto con un solo click è comunque impagabile. Vediamo quindi un semplice script bash che consente di svolgere l'operazione:

#!/bin/bash

# mi sposto alla cartella generale del progetto
cd ../../../

# genero il nome della cartella di dump
dumpDir="dump."$(date +%Y%m%d%H%M)

# creo la cartella di dump
mkdir $dumpDir

# scarico il sito
ncftpget -f etc/ftp.conf -T -R -F -v $dumpDir/ /httpdocs/*

# esco con il codice di uscita di ncftpget
exit $?

Questo ovviamente è un esempio e va adattato allo scenario in cui viene utilizzato. Per esempio alla riga 4 viene effettuato un cambio di directory che risale di tre livelli, questo perché nel nostro standard gli script bash dei singoli siti si trovano sempre in cartellaprogetto/versione/_src/_sh/ e quindi per poter operare a livello di cartella generale del progetto lo script deve risalire di tre livelli. Alla riga 13 invece viene assunto che il sito sul server di produzione si trovi in una cartella httpdocs/ il che ovviamente non è sempre vero quindi anche qui dovrete adattare lo script alle vostre esigenze.

Va infine osservato che lo script presuppone che nella cartella del progetto esista una sottocartella etc/ contentente un file ftp.conf nel quale siano riportate le informazioni necessarie a ncftp per funzionare. Ah, ovviamente il tutto dà per scontato che sulla vostra macchina sia installato ncftp.

esempio 2 — upload del sito web via FTP

Un'altra operazione che viene fatta abbastanza di frequente è l'upload del sito dal server di test a quello di produzione; anche in questo caso uno script può sveltire l'operazione.

#!/bin/bash

# mi sposto alla cartella generale del progetto
cd ../../../

# per procedere verifico che esista il file di configurazione necessario
if [ -r "etc/ftp.conf" ]; then

    # carico il sito
    ncftpput -R -f etc/ftp.conf -T -F -v /httpdocs/ stable/*

else

    echo "non posso leggere il file di configurazione"

fi

Lo script funziona in maniera analoga a quello dell'esempio precedente e valgono pertanto le stesse raccomandazioni riguardo alla personalizzazione. Inoltre si tratta di una procedura abbastanza «rozza» poiché lo script copia l'intero sito e non soltanto i files effettivamente aggiornati, quindi non è ottimizzato per ridurre il consumo di banda. Diciamo che è soprattutto per dare l'idea, se vi serve qualcosa di più avanzato provate anche lftp.

esempio 3 — dump del database

Effettuare facilmente il dump del database del sito è un'altra cosa comoda (non sto parlando di backups, che vanno affrontati con un'altra filosofia, ma di dumpfiles comodi ad esempio per l'upload in produzione) includendo solo i dati delle tabelle importanti (o viceversa escludendo esplicitamente i dati quelle inutili). Anche qui non concentriamoci tanto sulla posizione dei vari files di configurazione ma sul concetto generale dello script.

#!/bin/bash

# mi sposto alla cartella generale del progetto
cd ../../../

# file di configurazione con i dati per l'accesso al db
fileConf="/etc/mysql.conf"

# includo il file di configurazione locale
. etc/mysql-bash.conf

# per procedere verifico che esista il file di configurazione necessario
if [ -r $fileConf ]; then

    # esportazione dello schema vuoto
    /usr/bin/mysqldump --defaults-extra-file="$fileConf" \
        --opt --routines --no-data "$dbName" > etc/mysql.schema.sql

    # esportazione dei dati dalle tabelle essenziali
    /usr/bin/mysqldump --defaults-extra-file="$fileConf" \
        --opt --no-tablespaces --no-create-info --tables "$dbName" \
        "_anagrafica" "_anagrafica_accounts" > etc/mysql.data.sql

else

    echo "non posso leggere il file di configurazione"

fi

Qui presupponiamo l'esistenza di un file /etc/mysql.conf con i dati di accesso al server di database — ricordate che non è mai una buona idea inserire le password direttamente negli script, nonché un file ./etc/mysql-bash.conf che contiene altre info tipo la dichiarazione della variabile dbName. Ognuno di voi può ovviamente sbizzarrirsi come preferisce con i propri files di configurazione.

La separazione fra struttura e dati è comoda perché non sempre il contenuto delle tabelle sul server di sviluppo è utile in produzione — o non il contenuto di tutte le tabelle comunque. Qui a titolo di esempio ho specificato i nomi di due tabelle, ovviamente avrei potuto anche dichiarare una variabile in ./etc/mysql-bash.conf.

esempio 4 — ridimensionamento di immagini

Come ultimo esempio di questo articolo prendiamo un'altra operazione che viene svolta di frequente, ovverosia il ridimensionamento di immagini da inserire, per esempio, in un catalogo prodotti.

#!/bin/bash

# pulisco lo schermo
clear

# mi sposto alla cartella della versione corrente del progetto
cd ../../

# la cartella che contiene i files grezzi (raw) pronti per il ridimensionamento
cartellaBase=var/catalogo/immagini/rw/

# creo i files temporanei
listaBase=`mktemp`

# lista dei ridimensionamenti da fare
listaDimensionamenti=../etc/catalogo.dimensioniImmagini.conf

# genero la lista dei files da lavorare in TMP
ls -t $cartellaBase -1 > $listaBase

# ciclo sulle immagini trovate nella cartella base
while read nomeFileCorrente ; do

    # file correntemente elaborato con path completo
    fileCorrente="$cartellaBase$nomeFileCorrente"

    # ciclo sui dimensionamenti configurati nel file
    while read dimensionamento ; do

        # ricavo i dati dallo schema di dimensionamento
        datiDimensionamento=($dimensionamento)
        nomeStep=${datiDimensionamento[0]}
        dimensioneMassima=${datiDimensionamento[1]}x${datiDimensionamento[1]}
        qualita=${datiDimensionamento[2]}

        # nome del file di destinazione
        fileDest=${fileCorrente//rw/$nomeStep}

        # verifico che la cartella di destinazione esista
        mkdir -p $(dirname $fileDest)

        # scalo l'immagine
        convert -geometry $dimensioneMassima -quality $qualita $fileCorrente $fileDest

    # fine ciclo sui ridimensionamenti
    done < $listaDimensionamenti

    # elimino il file grezzo, che e' un doppione del file archiviato per data
    rm -f $fileCorrente

# fine del ciclo sulle immagini trovate nella cartella base
done < $listaBase

# fine dello script
exit 0

Questo script lavora molto bene e consente al cliente di caricare le immagini via FTP sul sito senza doversi preoccupare di ridimensionamenti e di associazione delle immagini agli oggetti di catalogo. È sufficiente che il file abbia un nome convenzionale (codice dell'oggetto e tipo di foto separati da un punto), dopodiché lo script si occupa di scalare le immagini secondo le informazioni contenute in un file di configurazione organizzato in questo modo:

xl 800x800 86
im 480x480 86
th 128x128 86

Ovviamente lo script è strettamente legato allo schema di database che utilizziamo nel nostro standard, ma contiene diversi spunti interessanti (l'utilizzo di convert per ridimensionare le immagini, la tecnica impiegata per rinominare i files, eccetera).

conclusioni

Gli script di shell consentono di svolgere in maniera automatica numerosi compiti complessi e danno un enorme valore aggiunto al sito dal punto di vista del cliente sia per quanto riguarda la gestione dei contenuti sia sotto l'aspetto delle performances del CMS. Grazie agli script è possibile fornire un servizio migliore al cliente risparmiando tempo e riducendo le possibilità di errore e interruzione di servizio.

Tutto il tempo che impiegate a scrivere dei buoni script è tempo che risparmierete in seguito, alzando contemporaneamente il livello qualitativo del lavoro. Se siete dei web designer e lavorate in ambiente Linux considerate seriamente la possibilità di studiare lo scripting Bash o approfondire le vostre conoscenze in materia.