venerdì, 19 Aprile 2024

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.

LVM, gestore logico dei volumi su Ubuntu [per pinguini alle prime armi]

Obiettivo: ampliare lo spazio su un disco di Ubuntu, aggiungendo un nuovo hard disk ed estendendo il disco con LVM

Prima di inoltrarci in questa guida sui volumi logici suggerisco di dare un’occhiata, per chi fosse ancora alle prime armi, a questo articolo sull’installazione di Ubuntu con LVM. Questo articolo prosegue sulla medesima configurazione dell’articolo citato, dove si suppone che abbiamo già installato Ubuntu predisponendolo per utilizzare l’LVM.

Quello che faremo sarà aggiungere un nuovo disco da 50 GB e poi aggiungere un altro disco da 20 GB col quale espandere il precedente.

LVM sta per logical volume manager (ovvero gestore logico dei volumi) un meccanismo attraverso il quale Linux può accorpare diversi dischi fisici in un’unico volume logico. E’ qualcosa che assomiglia, e sottolineo che si tratta solo di una somiglianza, alle configurazioni in RAID. L’idea potrebbe essere schematizzata nel modo seguente:

Il concetto di fondo è molto semplice e potremmo riassumerlo nel modo seguente: con due hard disk da 50 GB ciascuno posso creare un’unico “disco logico”, ovvero lo spazio che vede il sistema operativo, da 100 GB e posso continuare ad incrementarlo a piacere in base alle mie esigenze. Noi quindi aggiungeremo un disco 50GB e poi lo estenderemo con uno da 20GB, ottenendo uno spazio complessivo di 70GB.

Le potenzialità del LVM non si esauriscono qui, ma per quello che ci serve sapere in questo momento tanto può bastare.

In questo articolo utilizzerò ancora una volta VirtualBox, dove andrò ad aggiungere, al disco già esistente, puta caso da 50GB un secondo disco sempre da 50GB con il quale estendere la memoria a disposizione del mio sistema operativo.

Per aggiungere un nuovo disco alla mia macchina virtuale è sufficiente spostarsi, da VirtualBox, sulle Impostazioni della macchina virtuale e poi su Archiviazione.

A questo punto, come nell’immagine seguente, ci posizioniamo sul Controller SATA e clicchiamo sull’icona col disco ed il più verde e seguiamo la procedura guidata per aggiungere un secondo disco (da me chiamato DiscoUbuntuEsempio2.vdi) da 50 GB.

Fatto questo avviamo la nostra macchina virtuale come al solito. Inutile dire che se stessimo lavorando su una macchina fisica sarebbe sufficiente aggiungere fisicamente un nuovo hard disk al controller SATA.

Una volta dentro Ubuntu andiamo anzitutto a visualizzare l’elenco dei dischi fisici attualmente configurati.

Faccio notare che pv sta per phisical volume, ovvero i dischi fisici collegati all’LVM. Il risultato dovrebbe essere qualcosa di simile a questo.

Nel mio caso ho già collegato il secondo disco, ma solo un disco, quello dell’installazione, è configurato all’interno dell’LVM. Il disco nello specifico è /dev/sda5. (per essere precisi il disco è /dev/sda, mentre quello è il puntatore ad una delle “partizioni” — senza entrare troppo nel merito, che in questo momento potrebbe solo confondere le idee, possiamo dire che un singolo disco, sda in questo caso, può essere “visto” dal sistema operativo in diversi modi)

Adesso andiamo a visualizzare invece tutti i dischi collegati alla mia macchina.

Il risultato sarà esteso perché dovrebbe mostrare anche la RAM e tutti gli altri eventuali dischi e memorie collegati. Nel mio caso ad un certo punto appare:

Faccio notare che abbiamo due dischi, sda, di cui abbiamo parlato poc’anzi, e il nuovo disco sdb che abbiamo aggiunto da poco e che non è partizionato.

A questo punto creiamo una nuova partizione sul disco sdb.

Ci verrà chiesto che cosa vogliamo fare. Le opzioni in questo momento sono:

  • n = nuova partizione
  • p = partizione primaria
  • 1 = imposta la partizione la prima del disco

Scegliamo n per creare una nuova partizione.

Adesso ci viene chiesto se vogliamo farla primaria (p) o estesa (e). Scegliamo p per farla primaria.

Numero della partizione: 1

Alla domanda sul first sector, primo settore, digitiamo il valore suggerito di default, per me 2048.

Stesso discorso per il last sector, ovvero l’ultimo settore, scegliamo il valore suggerito di default (si può anche premere semplicemente INVIO)

Adesso abbiamo creato il nostro disco da 50GiB (ricordo che secondo il nuovo standard GiB sta per Gibibyte, che equivalgono a 1024 MiB, mentre 1GB equivale a 1000 MB, quindi 1 GiB ≠ 1 GB, inutile dire che per gli irriducibili come il sottoscritto si continuano a chiamare Gigabyte e andare di 1024 in 1024)

Continuando a trovarci su fdisk (che ci chiede un nuovo comando per proseguire o m per la guida), andiamo adesso a modificare il tipo di partizione creata digitando t e premendo INVIO.

  • t – modifica tipo di partizione
  • 8e – imposta su tipo LVM

Ci verrà chiesto il tipo di partizione e digitiamo 8e.

Se digitiamo L, alla richiesta del tipo di partizione, ci verrà mostrato il seguente elenco:

Se abbiamo fatto tutto bene ci verrà mostrato il seguente messaggio di conferma:

A questo punto è il momento di scrivere la partizione creta sul disco! Già, non l’abbiamo ancora scritta quindi nessuna di queste modifiche è ancora stata apportata. Le opzioni utili adesso sono:

  • p = mostra le impostazioni di partizione prima della scrittura
  • w = scrivi sul disco

Per scrupolo digitiamo p e verifichiamo che sia uscito qualcosa di simile.

Notiamo che sarà creato un puntatore /dev/sdb1 alla nuova partizione che ci accingiamo a creare.

Adesso premiamo w per scrivere tutte le modifiche sul nostro disco (inutile dire che ogni eventuale dato sul disco andrà perso).

Se tutto è andato bene riceveremo un messaggio di conferma come il seguente:

Adesso dobbiamo creare il nostro volume fisico. Da terminale digitiamo:

Adesso creiamo un nuovo gruppo dei volumi (in questo caso abbiamo un singolo volume) e lo andiamo a chiamare secondo-gruppo (il gruppo esistente, come visto con pvdisplay si chiama ubuntu-vg, il nome è a piacere purché sia una parola singola). Digitiamo:

Adesso dobbiamo creare soltanto il volume logico e dargli un nome, per esempio spazio-web. Tra poco capirete meglio anche la scelta, intanto procediamo con:

Faccio notare che abbiamo creato così un volume logico di 10GB (passando la dimensione al comando -L 10G) sullo spazio complessivo disponibile di 50GB. Se avessi voluto utilizzare tutto lo spazio anziché passare il comando -L avrei dovuto scrivere

Il motivo per cui scelgo di non usare tutto lo spazio, o per essere più precisi uno dei motivi possibili, potrebbe essere il seguente: questo disco intendo dedicarlo allo spazio web in /var/www montandolo al posto della cartella esistente. Così tutti i siti web ospitati dal mio server si troveranno su un disco separato da quello principale. In questo modo posso anche controllare l’espansione di tali siti, evitando che mi saturino l’intero disco prima che io possa espanderlo. Qualora la dimensione dei siti dovesse raggiungere i 10GB, i loro utenti (che in teoria potrebbero avere degli accessi dedicati allo spazio web, per esempio mediante FTP) non potranno aggiungere altri file, mentre io potrò espandere lo spazio e adoperarmi per aggiungere nuovi hard disk.

Per chiarire questa idea immaginiamo di ospitare sul server il sito web di Mario e quello di Luigi, due persone distinte e che non si conoscono. In tutto i loro siti condividono 10GB in questo momento; immaginiamo adesso che Luigi decida di caricare sul proprio server web 3 file da 9GB. Dopo il primo upload lo spazio sarebbe saturato e Luigi non potrebbe proseguire con il successivo. Questo provocherebbe degli alert (supponendo che io li abbia configurati) all’interno della macchina e mi permetterebbe di intervenire in due modi: anzitutto controllare come mai lo spazio è cresciuto a dismisura in poco tempo, e allo stesso tempo aggiungere magari un altro paio di GB per permettere a Mario di essere comunque operativo e non sentire la saturazione dello spazio condiviso.

Concludiamo tutta l’operazione formattando il nuovo volume logico appena creato:

mkfs sta letteralmente per make filesystem e il comando -t mi permette di scegliere il tipo di file system.

Controlliamo la situazione digitando di nuovo:

Dovremmo vedere qualcosa di simile a questo:

Questi sono i nostri due volumi fisici. Controlliamo adesso quelli logici digitando:

Quello che dovrebbe apparirci è la seguente schermata:

In questo caso abbiamo due gruppi distinti di volumi e tre volumi logici. I due gruppi sono ubuntu-vg e secondo-gruppo, mentre i tre volumi logici sono spazio-web, root e swap_1.

Adesso montiamo il volume logico spazio-web sulla cartella /var/www/.

Attenzione! Montando il volume su uno spazio esistente tutto il contenuto di tale spazio verrà sovrascritto, quindi prima dovremmo copiare dentro il nuovo volume il contenuto attuale. I vecchi dati comunque non andranno persi, semplicemente non saranno più visibili. Per capire bene questo passaggio facciamo la seguente serie di operazioni.

Anzitutto controlliamo il contenuto della cartella /var/www digitando:

Quello che dovremmo vedere (ricordo che sulla mia macchina ho già configurato altri virtual host e siti) è qualcosa di simile a:

Il contenuto non è tanto importante quanto il fatto che dentro ci sia già qualcosa che vorremmo preservare.

Adesso montiamo su /var/www il volume spazio-web.

A questo punto controlliamo nuovamente, come prima il contenuto della cartella /var/www

Il risultato che dovrebbe presentarsi è qualcosa di simile a questo:

Notiamo che non ci sono le cartelle di prima ma solamente una cartella lost+found che si trova anche nella radice (root) del nostro sistema operativo.

Nota: la cartella lost+found esiste su ogni partizione primaria ed ha come scopo quello di collezionare eventuali file danneggiati, perduti o recuperati da fsck (per esempio). Dentro a lost+found possono finire anche file o frammenti di file a seguito di un errore di sistema (es. kernel panic) o un arresto improvviso, oppure per via di inconsistenze del sistema dovute a software o altri generi di errori. In generale quello che si trova dentro a lost+found può essere cancellato perché già eliminato dal sistema o inutile.

A questo punto, a scopo dimostrativo, creiamo dentro la cartella /var/www un file vuoto chiamato file_petar_test.txt con il seguente comando:

Questo lo facciamo per verificare il comportamento di mount (chiaramente non è necessario per una configurazione normale).

Adesso smontiamo la partizione in modo da copiare il contenuto originale di /var/www nella nuova partizione prima di montarla di nuovo:

Il comando umount smonta la cartella scelta. Effettuando di nuovo un ls sulla cartella /var/www ritroveremo i file precedenti:

Adesso montiamo la partizione (il volume logico) spazio-web su una cartella provvisoria che creeremo dentro a /mnt (la cartella /mnt è pensata per creare dentro le cartelle sulle quali montare volumi aggiuntivi — come è facile immaginare non c’è niente di speciale in tale cartella e il mount può essere effettuato ovunque).

Creiamo quindi la cartella provvisoria con:

Faccio notare che il nome cartella_sw è totalmente arbitrario, l’unica condizione è che rispetti i criteri per la creazione delle cartelle in generale (sw starebbe nel mio caso per spazio-web).

Montiamo la partizione:

A questo punto possiamo copiare il contenuto da /var/www in /mnt/cartella_sw (se controlliamo il contenuto di quest’ultima cartella noteremo il nostro file txt di prova creato in precedenza)

In questo caso usiamo il comando cp per copiare, con il parametro -a gli diciamo di copiare ricorsivamente tutte le cartelle ed i file figli della cartella genitore. E’ importante scrivere /var/www/. (ovvero il percorso con incluso il punto) perché il . rappresenta il contenuto della cartella, stiamo cioè dicendo a cp che non vogliamo copiare anche /var/www, ma soltanto il suo contenuto e tutti i suoi figli.

Controllando con ls il contenuto di /mnt/cartella_sw ci accertiamo di aver copiato tutto ciò che c’era dentro a /var/www, troveremo ovviamente anche il file di prova creato precedentemente e lost+found.

A questo punto possiamo rimontare il volume logico sulla posizione /var/www (ricordiamoci di smontarlo dalla posizione corrente e cancellare la cartella /mnt/cartella_sw, lo facciamo solo per una questione di ordine). In sequenza eseguiamo quindi:

Controllando il contenuto di /var/www a questo punto dovremmo vedere qualcosa di simile a:

Inutile dire che, in linea di principio, se questa fosse stata un’operazione definitiva, avrei dovuto svuotare il contenuto di /var/www per non occupare inutilmente lo spazio sul disco primario.

A questo punto vediamo alcuni altri comandi utili.

DF, PVS e LVS

Con il comando df (disk free) controlliamo lo spazio sulle partizioni montate.

Il risultato dovrebbe essere simile a questo:

Notiamo che il volume logico ubuntu–vg-root (qui il formato è gruppo_volumi-volume_logico) è montato su / (la radice del sistema), mentre secondo–gruppo-spazio–web è montato su /var/www. Ci vengono mostrate anche le percentuali di utilizzo, 1% nel caso di /var/www.

Adesso vediamo le informazioni sui volumi logici utilizzando lvs.

Faccio notare che, a differenza di df, questo necessità di permessi di root per essere eseguito.

In questo caso ci vengono mostrate le informazioni su tutti i volumi logici che abbiamo creato, comprese le loro dimensioni.

Utilizziamo adesso pvs per visualizzare i volumi fisici:

Quello che otteniamo dovrebbe assomigliare al seguente risultato:

In questo caso vediamo i volumi fisici associati all’LVM, ed in particolare possiamo controllare lo spazio complessivo (PSize) e lo spazio libero (PFree). In particolare notiamo che su sdb1 abbiamo ancora 40GB liberi.

Quindi, riepilogando, abbiamo destinato il volume logico spazio-web, appartenente al gruppo secondo-gruppo, alla cartella /var/www. Il gruppo secondo-gruppo contiene in tutto spazio per 50GB, di cui stiamo usando solo 10GB per il volume logico spazio-web.

Estendere un volume logico

Adesso vogliamo dare altri 20GB allo spazio-web, espandendo quindi /var/www.

Per farlo ci sarà sufficiente utilizzare il comando lvextend:

Ci verrà data conferma che l’estensione è avvenuta con successo; l’estensione può avvenire finché il gruppo dei volumi a cui appartiene il volume logico dispone di spazio libero (PFree).

Utilizziamo di nuovo df -h per verificare la situazione:

E dovremmo vedere qualcosa di simile a questo:

Notiamo che /var/www continua ad essere di 10GB! Questo perché oltre ad estendere il volume logico dobbiamo estendere anche il filesystem. Per farlo ci è sufficiente digitare:

Ricontrollando con df -h vediamo che la situazione è diventata come la volevamo all’inizio:

Aggiungere volume fisico al gruppo dei volumi

Aggiungiamo adesso un disco fisico da 20GB al gruppo dei volumi chiamato secondo-gruppo, in modo che lo spazio complessivo passi da 50GB a 70GB.

Per farlo dobbiamo aggiungere naturalmente un nuovo disco, io lo faccio sulla macchina virtuale in questo caso. Verifichiamo i dischi collegati:

Il nuovo risultato dovrebbe essere simile al seguente:

Notiamo che abbiamo un disco su /dev/sdc da 20GB.

Adesso aggiungiamo il disco al gruppo di volume chiamato secondo-gruppo:

Controlliamo i nostri volumi fisici con:

Questo è il nuovo risultato:

Vediamo che su secondo-gruppo abbiamo ancora liberi 40G (la somma degli spazi liberi sui due dischi precedenti), quindi proviamo ad estendere spazio-web di altri 40GB, oltre ai 20GB precedentemente aggiunti. Eseguiamo i seguenti due comandi, come prima:

Eseguendo questo comando ci viene però detto “Insufficient free space: 10240 extents needed, but only 10238 available“, ci mancano giusto 2 extents (gli extents sono l’equivalente per le LVM dei cluster per i filesystem, entrambi sono le minime unità in cui viene suddiviso lo spazio). Per evitare il problema estendiamo il volume logico su tutto lo spazio disponibile:

Notiamo come il comando assomigli al medesimo meccanismo, eccetto per il +, con il quale creiamo il volume logico su tutto lo spazio disponibile. Adesso estendiamo il filesystem.

Prima di poterlo fare potrebbe esserci richiesto un controllo del filesystem medesimo, visto che lo abbiamo esteso poc’anzi.

In questo modo eseguiamo il controllo e poi effettuiamo di nuovo resize2fs.

A questo punto eseguendo df -h notiamo che /var/www corrisponde a circa 70GB.

OK. Ho barato un po’. Arrivati a questo punto potreste in realtà notare che /var/www non è più collegata al volume logico spazio-web. Questo è successo se avete riavviato il computer per montare il secondo disco aggiuntivo. Per ottenere il risultato precedente è sufficiente montare di nuovo il volume logico, come in precedenza, oppure definire il mount in modo permanente (questo vale per qualunque disco, non solo per i volumi logici).

Montare un disco in modo permanente

Per montare il volume logico in modo permanente, ovvero che rimanga montato dopo ogni riavvio, è necessario modificare il file /etc/fstab.

Per montare il disco utilizziamo la seguente sintassi:

  • PERCORSO_VOLUME_LOGICO PUNTO_DI_MOUNT ext4 rw,defaults 0 0

Quindi in fondo al file scriviamo:

Faccio notare che /dev/mapper/secondo–gruppo-spazio–web è il percorso che ci viene dato da df -h

Salviamo e riavviamo la macchina per verificare se va tutto bene. ATTENZIONE! Prestate moltissima attenzione alla sintassi, un qualche errore potrebbe bloccare l’avvio del sistema e costringerci ad intervenire in modalità di ripristino. La soluzione sarebbe comunque semplice, basterebbe rimuovere l’ultima riga aggiunta a fstab.

Se tutto è andato a dovere eseguendo df -h vedremo /dev/mapper/secondo–gruppo-spazio–web montata su /var/www 

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:

Save Editor FF8

Di recente ho riscoperto la mia passione per Final Fantasy 8 grazie alla versione remastered di Steam. In realtà volevo rigiocare alla mia vecchia copia da PC, ma poi ho scoperto che non era più possibile installarla su computer a 64-bit (qualcuno suggeriva un’installazione in modalità provvisoria, per poi dover però correggere ben altri problemi!). Così mi sono messo alla ricerca di una soluzione ed ho scoperto che su Steam c’era una versione aggiornata e funzionante anche su Windows 10!

Vecchia copia da PC! Notare l’offerta per “internet gratis” con i vecchi modem 56k.

Adesso non starò ad approfondire i dettagli su questo gioco che amo profondamente (sì ok, quando ci giocai avevo anche una cotta per quel turbodisfattista di Squall), ma quando un gioco gira su PC inevitabilmente viene da chiedersi se ci sarà anche qualche modo meschino per crackarlo o modificarlo a proprio piacimento.

Ed ho scoperto che c’è! Ebbene sì, esiste già un programma perfettamente funzionante per modificare i file di salvataggio del gioco.

Il programma si chiama Hyne (1.9.2), ed è possibile scaricarlo in diverse versioni da Github.

Da quello che ho potuto testare funziona anche sulla versione Steam, e non appena finisco il gioco non mancherò di divertirmi con un po’ di OP.

Il programma è molto intuitivo ed offre una configurazione dettagliata tramite interfacce grafiche dedicate.

Una volta aperto il salvataggio (i salvataggi di Steam si trovano di predefinito nella cartella Documenti %USERPROFILE%\Documents\Square Enix\FINAL FANTASY VIII Steam\user_XXXXXX) ci si presenterà una schermata simile alla precedente, dove potremo selezionare il salvataggio che ci interessa.

Seguiranno una serie di schermate dalle quali sarà possibile modificare nei più piccoli dettagli le caratteristiche del gioco (io devo ancora giungere al garden di Galbadia)

Una volta fatto è sufficiente salvare il file. Consiglio naturalmente di tenere una copia di backup del file originale, per ogni evenienza.

Fonte: Hyne

Interrogare foglio di Excel con SQL in VBA

Obiettivo: interrogare e filtrare il contenuto di un foglio excel come se fosse una tabella di un database SQL

Prepariamo anzitutto un file Excel creando un foglio con dei dati come quelli di seguito:

Questo foglio lo chiamiamo DATI. Faccio notare che nella prima riga ho inserito le intestazioni della nostra tabella.

In un secondo foglio andiamo a creare un pulsante che richiamerà un form. L’idea sarebbe quella di creare un metodo di inserimento che guidi l’utente e gli permetta di filtrare una vasta base dati, eseguendo anche dei comandi di ricerca. Il risultato sarà il seguente:

Se proviamo a cercare qualcosa, per esempio “Mar” l’elenco dovrà essere filtrato e otterremo il risultato seguente:

Fatte queste premesse vediamo come realizzare l’interrogazione del foglio mediante VBA (sorvolo sull’elementare creazione del form).

Anzitutto creiamo una Sub che caricherà i valori nella combobox (cmbSeleziona) e nella listbox (lbSeleziona).

Faccio notare che in questo caso la query filtra solamente i valori in base al Nome, inoltre il parametro nome può essere passato in via opzionale, permettendo quindi anche di visualizzare tutti i campi se non c’è nessun nome da filtrare.

Ricordiamoci che per poter eseguire la connessione ADO abbiamo bisogno di importare l’opportuna libreria dai riferimenti.

A questo punto completiamo il nostro codice aggiungendo:

In questo modo ad ogni modifica (change) di txtCerca, che è la textbox di ricerca in cima al form, verrà interrogato il nostro foglio per produrre un risultato.

Il medesimo metodo LoadSelect, questa volta senza argomenti, lo aggiungiamo anche all’avvio del form, per caricare il contenuto completo senza filtri.

Qui è possibile scaricare il file creato con Excel 2016.

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

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.

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).

Labirinto disegnato in PHP

Per gli appassionati di Pathfinder come me capita di fare il master e voler proporre qualche simpatico labirinto ai propri avventurieri. Online si trovano già moltissimi generatori di dungeon, però ho deciso di svagarmi un po’ questo sabato pomeriggio creando uno tutto mio in PHP.

Questo è il risultato (si rigenera ad ogni refresh della pagina):

Vediamo il codice sufficiente per ottenerlo:

Le impostazioni nell’esempio sono le medesime per ottenere l’immagine di sopra.

Calcolare IRR (Internal Rate of Return o TIR.COST) in VBA

Problema: la funzione TIR.COST (Tasso Interno di Rendimento) restituisce un unico valore per l’IRR anche quando ce ne è più di uno

Senza discutere sull’interpretazione dell’IRR stesso, immaginiamo di avere i seguenti due scenari di flusso di cassa.

I Scenario

Questo produce un grafico VAN-IRR come quello seguente:

In questo caso abbiamo due valori dell’IRR rispettivamente 15,47% e 33,33%; la funzione TIR.COST restituisce solamente il primo valore.

II Scenario

A questa serie di flussi di cassa corrisponde il seguente grafico:

In questo caso abbiamo due valori dell’IRR rispettivamente 1,99% e 19,65%; la funzione TIR.COST restituisce solamente il secondo valore.

Costruiamo quindi in VBA le funzioni necessarie per effettuare questo calcolo; come già mostrato anche qui utilizzeremo una funzione che restituisca un vettore di valori sotto forma di Variant, in modo da poterli valutare singolarmente (per esempio utilizzando le funzioni MIN e MAX, quando i valori sono solo due, quindi =MIN(IRRX(A1:A10)) oppure =MAX(IRRX(A1:A10))).

La funzione finale si chiama IRRX, quella che utilizzeremo dentro il foglio excel.

Le altre funzioni servono rispettivamente a:

  • IRRv1 – calcolare in modo approssimativo tutti gli IRR possibili su uno specifico flusso di cassa, con valore massimo per l’IRR al 30.000% (espresso come max = 300), inutile dire come questo valore possa essere impostato anche a molto meno per velocizzare i calcoli; l’IRR qui viene calcolato per ogni punto percentuale con scarti del 1%
  • IRRv2 – qui calcoliamo, per ogni valore di IRR trovato con la precedente funzione, il valore approssimato mediante iterazione su valori che vanno da IRRv2 ± 1%
  • VAN – questa funziona calcola semplicemente il VAN sul dato IRR

 

Testato su Excel 2016.