[bash] Script per reimpostare i permessi della cartella system su Plesk

Oggi mi sono trovato di fronte al problema di reimpostare tutti i permessi sulla cartella /var/www/vhosts/system/ appartenente a Plesk.

Nel caso specifico esiste un articolo di riferimento della guida di Plesk su come reimpostare i permessi e quali dovrebbero essere quelli corretti. Per l’articolo originale vedere: How to restore default permissions in the virtual host directory on Linux?

Nell’articolo è possibile trovare anche un file bash che però non reimposta i permessi sulla cartella system.

Allora ne ho realizzato uno mio, seguendo lo schema dei permessi illustrato nell’articolo medesimo:

Il codice in bash è il seguente:

 

Vedi articolo

[bash] Copiare i file trovati con grep in una cartella di destinazione

L’obiettivo è quello di trovare determinati file con dentro un certo contenuto, utilizzando grep e copiarli in una cartella di destinazione (nel mio specifico caso per fini di backup).

Per farlo con bash ci è sufficiente digitare il seguente codice:

Nota che utilizzo cp -a per copiare tutte le caratteristiche del file, permessi compresi.

Vedi articolo

[linux] Rinominare i file da terminale con bash sostituendo uno o più caratteri nel nome

Immaginiamo di voler sostituire un particolare carattere nel nome dei file dentro ad una cartella. Nel mio caso in tutti i nomi è presente una @ che voglio trasformare in uno _.

Utilizzando semplici comandi di bash è possibile fare questa operazione da terminale nel modo seguente:

 

Vedi articolo

[mysql] Svuotare un database o eliminare tutte le tabelle da terminale (remove o truncate)

Obiettivo: eliminare oppure svuotare tutte le tabelle di un database con un singolo commando da terminale

Questa soluzione è molto utile specialmente se si devono svuotare numerosi database. Abbiamo due possibilità:

1. Eliminare le tabelle (drop)

2. Svuotare le tabelle senza eliminarle (truncate)

In entrambi i casi al posto di USER va messo l’utente del database, al posto di PASSWORD la password dell’utente sul database e al posto di DATABASE il nome del database sul quale vogliamo lavorare.

 

Vedi articolo

[bash] Disegnare fiocco di neve su terminale

Approfittando della giornata innevata e di un po’ di relax ecco un piccolo esercizio in bash per “disegnare” su terminale utilizzando semplicemente spazi e cancelletti (#).

Anzitutto creiamo una serie di funzioni che ci consentano di disegnare come se si stesse lavorando su un piano cartesiano. A tale proposito cerchiamo di disegnare una parabola con la seguente funzione:

y=x^2-5

Prima di proseguire installiamo il basic calculator, che ci permetterà di effettuare calcoli matematici elementari in bash (non è indispensabile, né l’unico modo, ma per quello che vogliamo fare dovrebbe essere sufficiente):

Una volta installato creiamo un file parabola.sh

Ed inseriamo dentro il seguente codice:

Ricordiamoci di rendere lo script eseguibile digitando:

Ed eseguiamolo:

Il risultato di questa operazione dovrebbe dare qualcosa di simile a questo:

Faccio notare che la funzione disegna accetta come terzo parametro il tipo di carattere che vorremo utilizzare.

Adesso che abbiamo verificato che il disegno sul piano cartesiano funziona possiamo scrivere la serie di istruzioni necessarie a generare il nostro simpatico fiocco di neve. Le funzioni matematiche necessarie le ho prese da qui: Snowflake Math.

Inutile dire che si potrebbero usare moltissime altre funzioni, oppure divertirci con un calcolo frattale. Notiamo però che il disegno accetterà solo valore naturali interi, quindi il risultato sarà comunque un po’ impreciso. Infatti non possiamo aumentare la densità di caratteri sul terminale, potendo così apprezzare altri dettagli. Lo script sarà dunque questo:

Il risultato dovrebbe essere qualcosa di simile a questo:

Non è bellissimo, ma è quello che stavamo cercando di fare. Perfezionando le equazioni probabilmente si può ottenere di meglio.

Vedi articolo

Configurare VirtualHost su Apache, database MySQL e accesso FTP per un utente con BASH

L’esercizio in bash che propongo stavolta consiste nell’automatizzare la configurazione di un hosting sul nostro server Apache, ovvero la configurazione del VirtualHost, di un nuovo utente e database MySQL e di un accesso FTP.

L’obiettivo è quello di arrivare ad avere uno script utilizzabile nel modo seguente:

I parametri che vogliamo passare al nostro script sono:

  • -u: il nome dell’utente che vogliamo creare
  • -d: il nome del dominio che vogliamo registrare come VirtualHost di Apache
  • –dbadmin: il nome utente dell’amministratore del database, quello in grado di creare altri utenti all’interno del MySQL
  • –dbpass: la password del suddetto utente del database MySQL

Questo ci darà occasione per esplorare diverse caratteristiche di bash.

Anzitutto vogliamo acquisire ed elaborare i vari parametri passati al nostro script. Finora abbiamo visto che i parametri possono essere letti usando $# per contare il numero di argomenti, $0 per visualizzare il nome dello script, $1 per prendere il primo parametro, $2 per prendere il secondo e via discorrendo.

Adesso vogliamo prendere un numero indefinito di argomenti e parametrizzarli, vediamo come fare:

Usiamo quindi un ciclo while che continuerà ad andare avanti finché il numero di parametri passati allo script non sarà 0. Quindi acquisiamo il primo parametro $1 e lo passiamo ad una variabile chiamata parametro. Utilizziamo adesso un interruttore (case…esac) per cui in base al valore di parametro si attiveranno diverse opzioni.

Ciascuna opzione è scritta nella forma

Qui al posto di valore può essere un singolo valore oppure un gruppo diviso da |, nella maniera di valore1|valore2. Al posto dei puntini ci va del codice a piacere che vogliamo attivare in base alla variabile. Il principio, concettualmente, è identico a quello della realizzazione del programma in bash con menu.

Il comando shift, in bash, rimuove gli argomenti passati ad uno script a partire dall’inizio della lista, cioè dal primo argomento. Questo significa che ad ogni ciclo del while non prenderemo il primo argomento, lo controlleremo e poi lo rimuoveremo dall’elenco. Quando si digita due volte shift, si estraggono due parametri.

Viene da se che se l’argomento $1 è, per esempio, uguale a “-d“, allora l’argomento $2 dovrà contenere il nome del dominio e quindi una volta letti li rimuoveremo entrambi.

Se invece l’argomento $1 fosse uguale a “-h” oppure a “–help“, allora visualizzeremmo, senza ulteriori opzioni, una guida allo script. In questo caso dovremmo rimuovere un solo argomento.

Fatto questo cominciamo ad elaborare i parametri acquisiti. Anzitutto controlliamo se sia stato passato un nome utente del database:

Se non c’è un nome utente del database chiamiamo una funzione che stampi l’errore:

In questo caso vogliamo usare, visto che possiamo, anche dei colori, e quindi colorare di rosso la parola “ERRORE!”. Per farlo facciamo riferimento all’ANSI escape code.

Quindi possiamo usare le seguenti combinazioni:

Questo significa che se nella string “ERRORE! C’è un errore” fosse scritto “\033[0;31mERRORE!\033[0m C’è un errore” la stringa verrebbe colorata tutta di rosso, fino al nuovo colore che è, in questo caso, quello nullo predefinito. Ovvero così:

Per comodità vogliamo parametrizzare alcuni colori inserendo, in cima allo script il seguente codice:

La variabile NC starebbe per No Color, ovviamente i nomi sono a piacere.

Fatto questo controlliamo se sia stata passata anche la password, se non è stato fatto la richiediamo:

Potremmo aggiungere altri controlli (per esempio sul nome del dominio, ecc.) ma per ora tralasciamo ed andiamo a creare la cartella del vhost sotto a /var/www.

Utilizziamo 2>/dev/null per reindirizzare l’output di un eventuale errore e non mostrarlo a schermo, mentre il connettore || vuol dire che, dati due comandi A e B per cui A || B, se A non va a buon fine, allora esegui B.

Fatto questo creiamo subito l’utente FTP dedicato e la relativa password. In questo esempio do per scontato che abbiamo installato ProFTPd e che sia già stato configurato correttamente sul nostro server:

Con il primo comando creiamo una password casuale di 12 caratteri.

Creiamo poi un utente chiamato come da argomento e assegniamo, alla cartella creata in precedenza, come proprietario l’utente appena creato e come gruppo www-data (ricordiamoci che sulla cartella deve poter interagire anche Apache). Fatta questa modifica con il comando usermod -d assegniamo la cartella alla home dell’utente. Questo viene fatto per motivi di sicurezza, per cui l’utente che accede al FTP acceda direttamente alla sua “home“, corrispondente anche allo spazio web.

Dopodiché impostiamo la password appena creata come password del nostro utente, ed infine stampiamola a video.

Faccio notare che perché –shell /bin/false non dia problemi, così come la questione della home, è necessario che nel file di configurazione di ProFTPd (/etc/proftpd/proftpd.conf) siano presenti i seguenti parametri così configurati (tipicamente va tolto il cancelletto):

Fatto questo scriviamo il nostro file del VirtualHost:

In questo caso vogliamo creare un file del tipo nomedominio.conf dentro a /etc/apache2/sites-available/, già che ci siamo sostituiamo il . con un _, in modo tale che nomedominio.com diventi nomedominio_com e il nome del file nomedominio_com.conf. Con l’istruzione EOF possiamo scrivere direttamente dentro il file il testo contenuto in mezzo.

Fatto questo ricarichiamo Apache:

Adesso ci manca solamente il database:

Anche in questo caso abbiamo creato una password che assoceremo ad un utente chiamato come il database medesimo e che ha accesso solamente dal server locale.

Infine, per testare il tutto (questo certo non sarebbe uno standard opportuno per un vero hosting) creiamo un file index.php nel VirtualHost appena configurato e inseriamo dentro i seguenti parametri:

Se tutto è andato bene collegandoci al dominio del hosting appena registrato dovremmo veder scritto Nome_Dominio under construction e nessun avviso di Errore database.

Aggiungo anche un’ultima funzione utile per ripristinare il tutto quando si usa il parametro –fix, cancellando quindi il vhost e le relative cartelle:

Il codice completo, riorganizzando quanto detto prima, è questo:

Il codice è stato scritto e testato su Ubuntu Server 16.04, con sopra installati Apache, MySQL, PHP, OpenSSL e ProFTPd.

Vedi articolo

Inviare comando POST a script in PHP mediante BASH

Per un po’ di svago pomeridiano propongo oggi un veloce esercizio che unisca bash e PHP. Quello che vogliamo fare è creare uno script che da console ci chieda quali dati inviare mediante POST ad una pagina in PHP, che poi li utilizzerà per conto proprio.

Anzitutto costruiamo una pagina PHP opportunamente posizionata nel nostro webserver come la seguente:

In questo modo la pagina riceverà dei dati dal form e li scriverà nel file dati.txt, poi leggerà il file dati.txt e lo stamperà a schermo prima del form. Inutile dire che si tratta di una pagina a scopo di prova e sarebbe assolutamente inopportuno utilizzare un simile meccanismo online.

Adesso vediamo come creare il nostro script in bash:

Ricordo che per creare il file bash, nella posizione che desideriamo sarà sufficiente digitare qualcosa come:

Una volta creato ed inseriti tutti i dati ricordiamoci di dargli i permessi necessari perché possa essere seguito:

Faccio notare che il nostro file in PHP si chiama index.php e si trova su un percorso raggiungibile da http://localhost/test/index.php

Eseguendo il file in bash dovremmo vedere qualcosa di simile sulla nostra console:

Vedi articolo

Creare un programma con menu e opzioni di scelta in bash

Per gli esercizi dedicati a bash ne propongo uno rielaborato da me qualche mese fa per un corso.

Obiettivo: creare un semplice programma in bash che mostri un menu a schermo e ci permetta di fare delle scelte; in particolare mostrare un elenco di alunni e voti, aggiungere nomi di alunni e relativi voti, svuotare il “database” (in questo caso nient’altro che un file di testo) ed uscire dal programma

Nel nome delle funzioni non c’è niente di speciale, in particolare nelle funzioni showmenu e do_menu che ho chiamato così solo per abitudine, avendolo imparato a mia volta da script in inglese (potremmo dire anche scopiazzato!).

Commentiamo adesso i punti salienti del codice:

Riga 6: show_menu non fa niente di speciale, stampa semplicemente a video una serie di scritte usando echo (quando si usa echo senza una stringa a seguire si ottiene un semplice accapo); l’unico punto veramente interessante è alla riga 15 dove con echo -en ci prepariamo ad acquisire un valore in input. Questo valore in input in realtà viene acquisito dal read nella funzione successiva (riga 24).

Nel caso specifico echo -en vuol dire che passiamo alla funzione echo due parametri

-n evita di aggiungere newline alla fine della stringa, ovvero non manda accapo

-e interpreta eventuali backslash

Per capire meglio come funziona proviamo a scrivere nel terminale le seguenti righe

Questo comando darà in output il seguente risultato

Il cursore si troverà in attesa alla fine della stringa ed i caratteri \t saranno trasformati in tabulazione.

Se invece scriviamo:

Verrà stampato a video:

Senza alcuna tabulazione.

Riga 22: cominciamo un ciclo while finché la variabile $i non sarà uguale a “q”.

Riga 24: leggiamo l’input dopo aver lanciato, alla riga precedente show_menu; l’input verrà letto nella variabile $i; dopo aver acquisito $i trasformiamo eventuali maiuscole in minuscole, in modo che sia premendo Q che q si possa uscire dal programma (questo non è ovviamente necessario, ma lo facciamo a titolo di esercizio).

A questo punto usiamo case per verificare la scelta in $i; in caso di qualsiasi scelta fuorché quelle elencate (riga 40) verrà mostrato un messaggio, qui scherzosamente sdubbiato.

Alla riga 36 invece, quando $i è uguale a “q” eseguiamo l’uscita dal programma con un saluto.

A questo punto costruiamo i metodi elencati dentro case.

Riga 48: il metodo mostra fa semplicemente il grep del contenuto del file e poi lo passa ad un ciclo while che legge ogni riga in $i. Il contenuto del file $ELENCO sarà scritto nel modo seguente:

Mario:10
Luigi:9
Anna:7

Ovvero un elenco di nomi separati da : dai voti; uno per riga. Quindi leggendo il file in righe sostituiamo ad ogni : una tabulazione in modo da stamparli a video uno sotto l’altro e con una tabulazione tra nome e voto.

Riga 55: creiamo il metodo per aggiungere nomi e voti; anche qui l’operazione è molto semplice e giochiamo un po’ con gli echo, per ottenere un’interfaccia da terminale decente. Alla riga 65 assembliamo i valori raccolti nelle precedenti due variabili in una singola stringa di testo che scriviamo sul file $ELENCO.

Riga 82: qui svuotiamo l’elenco degli studenti salvati in $ELENCO, semplicemente cancellando il contenuto dell’intero file. Notiamo qui l’uso diverso di >> e >. Il primo appende alla fine del file il contenuto, mentre > sostituisce l’intero contenuto. In questo caso lo sostituisce con una stringa vuota.

Riga 85: qui usiamo il comando $? per prendere l’output dell’ultimo metodo utilizzato, nel caso specifico il metodo conferma (riga 69). Il metodo conferma scrive a video una stringa presa da $@; la variabile $@ prende la lista di tutti gli argomenti passati al metodo, un po’ come fanno $0, $1 ecc per i singoli argomenti; in questo caso significa semplicemente che li prendiamo tutti. Il metodo legge la risposta e la trasforma tutta in maiuscole, in modo tale che Y e y equivalgano entrambi ad una conferma. Se la risposta è tale la funzione restituisce 0, altrimenti 1. Utilizzando $? controlliamo questo valore restituito e se fa 0 allora cancelliamo tutti i dati, se fa 1 annulliamo la cancellazione.

Riga 93: lanciamo l’intero programma.

Riferimenti utili: base di programmazione in BASH

Vedi articolo

Verificare integrità file in bash

Presupposto: immaginiamo di avere una cartella sorgente di file e una cartella dove li abbiamo copiati, per esempio durante un backup o solo per sicurezza; a tale proposito rimando all’esercizio precedente di copia dei file in bash

Obiettivo: adesso vogliamo controllare che i file in destinazione siano identici ai file nella copia di sicurezza; un primo modo elementare potrebbe essere quello di confrontare la dimensione dei file, però questo non ci garantisce l’effettiva integrità e che nella medesima dimensione non ci siano in realtà contenuti differenti; un approccio migliore sarebbe quello di confrontare gli hash dei file di origine con quelli della copia. Attenzione però! Perché non dobbiamo solo confrontare i file esistenti, ma verificare anche la presenza di nuovi file o di file mancanti.

Vediamo quindi come scrivere questa procedura in BASH.

Fino alla riga 17 abbiamo ripreso il codice del precedente esercizio, con un’unica differenza: abbiamo impostato la variabile tot su -1.

In questo modo nella parte successiva possiamo verificare se non esiste alcuna cartella di backup; se c’è una cartella è la cartella bck0, per via della costruzione dell’esercizio precedente, e quindi tot sarà uguale a 0.

Dopodiché costruiamo un metodo chiamato controllo che prende in ingresso un unico argomento (intercettato con $1 all’interno del codice) che è la cartella sorgente. Alla riga 52 passiamo la cartella sorgente iniziale, mentre alla riga 26 passiamo la cartella figlia che troviamo in quella di partenza, in modo da ripetere il controllo in modo ricorsivo.

Alla riga 24 controlliamo, tramite l’if, che l’elemento che stiamo controllando sia una cartella. Se lo è passiamo la cartella al metodo controllo, altrimenti verifichiamo i file.

Per verificare il file lanciamo md5sum sul file originale e leggiamo il risultato come due colonne: hash e nomefile.

Il ciclo while in realtà effettua un’unica operazione, per ogni valore controllato verifichiamo anzitutto se esiste o meno all’interno del backup. Se non esiste lanciamo in output il messaggio alla riga 41. Altrimenti lanciamo il comando md5sum sul file nel backup; con lo stesso principio di prima effettuiamo la lettura dell’output mettendo il risultato in altre due variabili, ovvero hashbck e nomefilebck. A questo punto confrontiamo che i due hash siano identici, in caso contrario (!= vuol dire diverso) lanciamo un output, quello della riga 36.

Notiamo che se va tutto bene non viene lanciato alcun output, ma solo in caso di errore.

TODO: In questo controllo manca la verifica che eventuali file presenti nel backup non siano stati cancellati dalla cartella sorgente.

Vedi articolo

Semplice script di backup (copia di file) in bash

Vediamo creare un elementare sistema di backup in BASH. In questo caso supponiamo di avere, nella posizione in cui viene eseguito il codice, una cartella chiamata elementi, dentro la quale abbiamo tutti i file e le cartelle che desideriamo copiare dentro la destinazione di backup. La destinazione di backup è la medesima dello script (non entro ora nel merito sul buon senso di fare qualcosa di simile) dove verranno create n cartelle consecutive per tutti i backup effettuati. Le cartelle saranno quindi chiamate bck0, bck1bckn.

Faccio notare che la prima parte dello script, quella con il ciclo for, serve solo a contare il numero di cartelle di backup attualmente esistenti, per poter creare così la cartella successiva. Se non esiste alcuna cartella il contatore rimane a 0 e crea la prima cartella zeresima, chiamata bck0. Quando si usa la seconda volta le cartelle sono 1, la cartella bck0, e quindi la variabile tot assume valore 1. E così via ad ogni passaggio successivo.

Il backup vero e proprio viene effettuato nell’ultima parte del codice (le ultime due righe), dove creiamo la nuova cartella unendo il nome di dest al numero in tot e poi usiamo il comando cp -a (copia ricorsivamente tutti i file e le cartelle).

Vedi articolo