[magento2] Script esterno per rimuovere le immagini duplicate su tutti i prodotti

Obiettivo: leggere tutti i prodotti del negozio su Magento 2 e eliminare tutte le immagini duplicate per ciascun prodotto.

In Magento 2 può capitare di ritrovarsi prodotti con immagini duplicate, specialmente a seguito di una importazione di dati. Inoltre sembra che ci siano anche dei bug, o almeno ci sono stati nelle diverse versioni, che producevano questo fastidioso problema.

Quello che vogliamo fare è creare una pagina correggi_immagini.php, nella root del sito, richiamando la quale percorreremo tutti i prodotti in cerca di immagini duplicate e le elimineremo.

Come piccolo accorgimento voglio che lo script sia eseguito solo a seguito di una specifica chiamata GET sulla pagina, per esempio /correggi_immagini.php?auth=1234567890abcdefghilmnopqrstuv

Al posto di 1234567890abcdefghilmnopqrstuv raccomando di sostituire un codice sufficientemente complesso.

Nei commenti ho inserito i dettagli sullo sviluppo dello script:

Vedi articolo

Errori durante il file upload con PHP, Apache & nginx

Riallacciandomi al precedente articolo ([php] Configurare php.ini per l’upload dei file) voglio approfondire il problema del caricamento di file di grosse dimensioni su server che utilizzano PHP, Apache e nginx (nel mio caso specifico anche Plesk).

Gli errori che possono sorgere sono difatti innumerevoli e spesso apparentemente senza senso.

Cominciamo riepilogando il necessario per quello che riguarda il PHP. Come spiegato nel precedente articolo, assicuriamoci di avere una configurazione simile alla seguente nel file php.ini

In questo caso sto supponendo che caricheremo file fino a 512MB.

Per quanto riguarda il PHP ci dobbiamo assicurare che la quantità di memorie allocabile sia compatibile con la dimensione dei file da caricare e che lo sia anche il tempo di esecuzione.

Con un tempo di 1200 secondi si suppone che l’upload avverrà ad un minimo di 0,43MB/s. Questo significa che parte del caricamento dipende anche dalla velocità di upload del client, che potrebbe non essere sufficientemente alta da permettere al server di terminare l’operazione nei tempi consentiti.

Per inciso ricordiamoci che le classiche connessioni ADSL 20 Mega hanno upload che si aggirano attorno a 1 Mbit, ovvero 0,12 MB/s. Questo significa che il tempo di esecuzione dovrebbe essere per lo meno di 4.300 secondi (approssimando per eccesso).

Detto tutto questo si potrebbe incorrere in altri problemi, come ad esempio, lato client: Failed to load resource: net::ERR_HTTP2_PROTOCOL_ERROR

Se si sta tentando di gestire l’upload tramite javascript e si incorre in questo errore, esso nulla ha a che fare con il protocollo HTTP/2 (e tanto meno è utile tornare al HTTP/1.1 o simili), ma è legato al fatto che la pagina non invia una risposta corretta. La risposta non viene inviata correttamente perché ad interrompere l’upload possono essere Apache oppure nginx.

Controllando il log del server si potrebbe trovare infatti un errore simile al seguente: 19855#0: *532 client intended to send too large body: 180584796 bytes

In questo caso sto cercando di caricare circa 172MB di file ed nginix blocca l’operazione.

Nel mio caso specifico posso verificare la cosa, confrontando su Windows la dimensione dei file che sto tentando di inviare al server con un unico upload.

Si può notare come la dimensione bloccata sia leggermente più grande dei file in upload, perché, come già discusso nel precedente articolo, il corpo che viene inviato al server contiene anche informazioni aggiuntive che vanno al di là dei singoli file che si stanno caricando.

A questo punto dobbiamo intervenire su nginx aggiungendo l’istruzione:

La configurazione predefinite di nginx sarebbe di 1m, mentre sotto Plesk è di 128m.

Questo parametro può essere modificato all’interno del file /etc/nginx/nginx.conf

Per farlo su Plesk procediamo nel modo seguente (è anche spiegato nella vademecum ufficiale, anche se ci sono delle piccole incongruenze):

  1. Colleghiamoci via SSH al Server con Plesk
  2. Creiamo un file di configurazione aggiuntivo a cui aggiungeremo l’istruzione precedente: echo 'client_max_body_size 128m;' > /etc/nginx/conf.d/aa_client_max_body.conf
  3. Verifichiamo se esiste il file /usr/local/psa/admin/conf/panel.ini
  4. Se non dovesse esistere creiamolo copiandolo dal file predefinito: cp /usr/local/psa/admin/conf/panel.ini.sample /usr/local/psa/admin/conf/panel.ini
  5. Aggiungiamo l’impostazione per la massima dimensione del corpo: echo -e "[webserver]\n nginxClientMaxBodySize = 512m\n" >> /usr/local/psa/admin/conf/panel.ini
  6. Modifichiamo i permessi: chmod 644 /usr/local/psa/admin/conf/panel.ini
  7. Riconfiguriamo il tutto: plesk sbin httpdmng --reconfigure-all
  8. Riavviamo nginx: service nginx restart
  9. Assicuriamoci che su tutti i webserver sia configurato il parametro giusto: nginx -T | grep client_max_body_size
  10. Nel caso non lo fosse possiamo usare l’istruzione, per riconfigurare il tutto: plesk repair web -y -v

In generale dovremmo assicurarci che, rispetto ai parametri suddetti, nelle configurazioni di nginx, sotto la voce server, compaiano i seguenti due valori:

Questi valori dovrebbero essere in linea (o superiori) con quelli scelti per il PHP.

Infine dobbiamo verificare che anche Apache consenta l’esecuzione dell’upload. Nel caso specifico potrebbero esserci due parametri ad influenzarlo: FcgidMaxRequestLen  e LimitRequestBody

Impostiamoli nel modo seguente:

Se abbiamo configurato tutto correttamente dovremmo essere in grado di caricare i file come definito all’inizio.

Vedi articolo

[php] Configurare php.ini per l’upload dei file

L’upload dei file, nel PHP, dipende da diverse parametri, alcuni diretti ed altri indiretti, configurabili nel php.ini.

Anzitutto individuiamo il file di configurazione in uso. Per farlo è sufficiente utilizzare, in una pagina php, l’istruzione phpinfo();

Otterremo un output simile a questo:

Nel mio caso specifico, sotto Plesk, il file si trova in /opt/plesk/php/7.3/etc/php.ini

In una configurazione predefinita di Ubuntu Server 19.10 avremmo qualcosa di simile invece:

Il percorso del file php.ini in questo caso è /etc/php/7.3/apache2/php.ini

Detto questo modifichiamo il suddetto file individuando le seguenti istruzioni:

upload_max_filesize

Questo è il parametro principale, quello che riguarda la massima dimensione di un file in upload. Di solito si trova impostato a 2M oppure 8M. Se volessimo consentire un upload di 20MB dovremmo metterlo a: upload_max_filesize = 20M

post_max_size

Questo parametro indica la massima dimensione dell’intestazione di POST, nel caso specifico se volessimo aumentare il valore a 20MB dovremmo digitare: post_max_size = 20M

Attenzione, perché il POST contiene non solo il file in upload, ma anche altre istruzioni. Con una dimensione di 20MB significa che il massimo file caricabile sarà probabilmente attorno ai 19MB, perché una parte del post è utilizzata per inviare anche altre istruzioni, per quanto in genere ridotte e piccole. Un’istruzione più corretta potrebbe essere: post_max_size = 21M

max_file_uploads

Questo parametro definisce invece il numero massimo di file caricabili. Di predefinito è impostato su 20, quindi si potranno caricare al massimo 20 file in una volta. Se volessimo consentire il caricamento simultaneo di 50 file, potremmo impostarlo come: max_file_uploads = 50

 

A queste, che sono le istruzioni specificatamente dedicate al caricamento dei file, se ne aggiungono altre che sono strettamente connesse.

memory_limit

Il limite di memoria allocabile dal processo di PHP per l’esecuzione delle operazioni. Nel caso di grossi caricamenti questo limite potrebbe dover essere aumentato. Di solito il valore è 128M, ovvero 128MB, se volessimo aumentare il valore a 256MB dovremmo scrivere: memory_limit = 256MB

max_execution_time

Il massimo tempo di esecuzione del processo PHP. Di predefinito è impostato su 30 secondi, il che vuol dire che se l’upload impiega più tempo il PHP chiuderà l’operazione allo scadere del limite del tempo. Possiamo aumentare questo valore, per esempio su 10 minuti (60 secondi x 10), digitando: max_execution_time = 600

max_input_time

Come prima, anche questo parametro concorre col precedente. Se il tempo massimo di esecuzione è inferiore a questo parametro il processo di input verrà comunque interrotto; viceversa se questo valore è basso l’input verrà interrotto secondo quest’ultimo parametro. Se vogliamo dare anche qui 10 minuti per il massimo tempo di input digitiamo: max_input_time = 600

 

Riassumiamo infine tutte quante le variabili assieme:

Vedi articolo

[php] Costruire un oggetto iterabile che possa essere percorso con foreach, grazie alle interfacce Iterator, ArrayAccess e Countable

Oggi propongo un semplice esercizio in PHP dove vogliamo costruire un oggetto iterabile che sia accessibile come un vettore e percorribile da foreach.

Immaginiamo di avere due classi Studente e Scuola, quello che vogliamo ottenere è il qualcosa di analogo a questo:

L’output sarà così:

in tutto ci sono 4 studenti
0 -> Squall
1 -> Zell
2 -> Rinoa
3 -> Edea

Anzitutto cominciamo costruendo la classe Studente. Questa è molto semplice e non ha nulla di particolare, la possiamo costruire come vogliamo ed in particolare, ai fini dell’esercizio, la farò con una sola proprietà e due metodi (set e get).

Adesso costruiamo Scuola implementando i metodi Iterator, ArrayAccess, Countable.

Le tre interfacce permettono di implementare diverse proprietà. Affinché l’oggetto costruito con Scuola sia percorribile dal foreach usiamo l’interfaccia Iterator.

L’interfaccia implementa i seguenti metodi astratti:

Si suppone che la nostra classe abbia una proprietà “posizione“, per cui si possa ricavare un valore da questa posizione corrente con current(). Il metodo key() dovrà restituire tale posizione corrente, next() permetterà di andare alla posizione successiva, mentre rewind() consentirà di ripartire dalla posizione iniziale. Infine il metodo valid() verificherà se nella posizione attuale esiste o meno un oggetto.

Cominciamo allora costruendo la classe nel modo seguente:

Per rendere la classe operativa aggiungiamo anche un altro paio di metodi. In particolare:

Con il controllo if( $studente instanceof Studente ) vogliamo assicurarci che l’oggetto aggiunto tramite il metodo add() sia del tipo Studente. Se il tipo non è quello giusto solleviamo un errore del tipo InvalidArgumentException dove avvisiamo l’utente.

Significa che la forma:

Produrrà un errore del tipo Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in iterator.php:92 Stack trace: #0 iterator.php(87): Scuola->erroreOggettoNonValido() #1 iterator.php(98): Scuola->add('Squall') #2 {main} thrown in iterator.php on line 92

L’operazione valida sarà invece:

A questo punto l’oggetto è già iterabile mediante foreach, che può essere chiamato nel modo seguente:

Vogliamo dare la possibilità di aggiungere gli oggetti anche alla maniera di $scuola[] = new Studente("Edea");

Per farlo implementiamo la nostra classe Scuola anche su ArrayAccess. L’interfaccia ArrayAccess richiede i seguenti metodi:

Quindi implementiamoli nella nostra classe Scuola alla maniera seguente:

Anche qui usiamo if( $value instanceof Studente ) per verificare che l’oggetto sia di tipo Studente. Nel metodo offsetGet() utilizziamo il null coalescing operator per restituire null nel caso in cui l’oggetto non esista.

A questo punto l’istruzione $scuola[] = new Studente("Edea"); diventa utilizzabile, mentre $scuola[] = "Edea"; produce il solito errore Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in...

Infine vogliamo poter usare il metodo count($scuola) sul nostro oggetto, ottenendo il conteggio di tutti gli studenti inseriti. Se lo usiamo senza ulteriori implementazioni il risultato sarebbe sempre e comunque 1.

L’interfaccia Countable richiede un unico metodo:

Implementiamolo nel modo seguente:

Probabilmente sarebbe stato più carino implementare un metodo interno alla classe, magari un contatore che tenesse conto delle aggiunte, ma ai fini dell’esercizio ci accontentiamo di chiamare count sul vettore interno degli studenti.

Fatto tutto questo vediamo il risultato finale così ottenuto:

Vedi articolo

[wordpress] Got error ‘crayon-syntax-highlighter/crayon_langs.class.php on line 340

Problema: Dopo l’aggiornamento al PHP 7.3 il plugin per WordPress Crayon Syntax Highlighter, utilizzato per evidenziare codici di programmazione, smette di funzionare e blocca la visualizzazione delle pagine nelle quali è utilizzato.

Soluzione: Modificare due file per rendere compatibile il riconoscimento per espressioni regolari con le nuove definizioni di PCRE2

L’errore che si presenta è tipo il seguente: AH01071: Got error 'crayon-syntax-highlighter/crayon_langs.class.php on line 340PHP message: PHP Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in

Purtroppo il plugin, per quanto buono, non è aggiornato da 4 anni.

In particolare presenta problemi con l’aggiornamento del PHP alla versione 7.3, per via delle nuove definizioni PCRE2 ed in particolare proprio per la presenza di un segno – (meno), proprio come trattato nel precedente articolo.

Per risolvere il problema facciamo nel modo seguente. Posizioniamoci nella cartella del plugin /wp-content/plugins/crayon-syntax-highlighter/

Modifichiamo il file crayon_langs.class.php alla riga 340

Sostituiamo la riga con:

Modifichiamo il file crayon_formatter.class.php alla riga 118

Sostituiamo le due righe con:

Fatto tutto questo il problema sarà risolto e potremo continuare ad usare il plugin.

Vedi articolo

Differenze e novità tra PHP5 e PHP7, con esempi di programmazione

Con la scusa di un po’ di esercizio vediamo anche quali sono le principali differenze tra (l’ormai vecchio) PHP 5 e il nuovo PHP 7 (che comunque è in circolazione già da un bel po’).

1. Sintassi flessibile per Heredoc e Newdoc
2. Operatore Spaceship
3. Null Coalesce Operator
4. Virgola finale negli argomenti di funzione
5. Migrazione a PCRE2
6. Unicode Codepoint Escape Syntax
7. Chiamata di errore nella codifica JSON
8. Exceptions per i fatal errors
9. Classi anonime
10. Dichiarazione del tipo di dato restituito
11. Metodo is_countable()
12. Primi e ultimi valori e chiavi di un array
13. Il metodo Closure->call
14. Prestazioni migliorate

1. Sintassi flessibile per Heredoc e Newdoc

Nell’ultimo aggiornamento del PHP 7.3 viene introdotta la possibilità di terminare il heredoc con UNA indentazione. Sottolineo UNA perché la cosa è un po’ comica, visto che una doppia indentazione (due tabulazioni) oppure degli spazi producono comunque errore.

In sostanza prima si doveva scrivere così:

Adesso è possibile scrivere così:

Questa singola tabulazione certo non farà la felicità assoluta di nessuno, però permette di aggiungere un po’ di chiarezza al codice (sebbene personalmente continui a trovarla una novità abbastanza inutile, tale qual’è).

2. Operatore Spaceship

A differenza della precedente, questa è una novità effettivamente significativa.

Viene introdotto l’operatore <=>, chiamato spaceship, che fa le veci (quasi ma non del tutto) della funzione strcmp. Questo velocizza la scrittura e ottimizza la sintassi, riducendo così il numero di passaggi a volte necessari.

Avendo il seguente codice:

Avremo il seguente output:

a <=> b : -1
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Utilizzando invece strcmp avremmo avuto il seguente codice:

Ed il seguente output:

a <=> b : -1
mario <=> maria : 14
marii <=> mario : -6
maria <=> mario : -14
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Come si può notare il comportamento non è identico, se consideriamo i valori numerici e non i segni.

Per riprodurre il comportamento dell’operatore spaceship in PHP 5 potremmo immaginare di scrivere una funzione simile a questa:

Applicandola all’elenco precedente:

Avremo gli stessi risultati di <=> in PHP 7:

a <=> b : 0
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Immaginiamo dunque di voler scrivere una funzione di ordinamento per un array. In PHP 5 avremmo potuto scrivere:

Mentre in PHP 7 possiamo sintetizzare con:

Entrambi i casi produrranno un output ordinato come il seguente:

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 7 [5] => 8 )

Inutile dire che per entrambi gli esempi avremmo potuto incorporare direttamente una funzione anonima dentro ad usort in questo modo:

Infine nel PHP 5 l’uso dell’operatore spaceship produrrebbe un errore di questo tipo:

Parse error: syntax error, unexpected '>' in /index.php on line 16

3. Null Coalesce Operator

In PHP 7 viene introdotto il null coalescing operator ??, proseguendo così le implementazioni sull’if lineare, già introdotte nel PHP 5.3 con l’Elvis operator ?:.

In generale sappiamo che possiamo scrivere un’istruzione con if lineare (o operatore ternario) di questo tipo:

Questa istruzione equivale a scrivere:

In generale questa istruzione può essere utilizzata per riassegnare la medesima variabile in uno dei due casi. Per esempio immaginiamo di voler scrivere:

Con l’Elvis operator possiamo sintetizzare la scrittura nel modo seguente:

Quello che viene assegnato è l’argomento del test. Se l’argomento del test comprende operatori logici viene assegnato il risultato dell’operazione logica.

Per capire meglio immaginiamo di voler trovare il più grande valore tra quelli dati (ci sarebbero altri mille modi, ma per lo scopo dell’esercizio prendiamo questo):

Il risultato di questa operazione darà ovviamente come risultato 8.

Se lo riscrivessimo con l’Elvis operator potremmo avere qualcosa del genere:

Purtroppo però il risultato non sarebbe più 8, bensì 1, e questo indipendentemente dal fatto che 1 esista nell’array. E’ 1 perché 1 è true, il risultato di una delle operazioni di test. (il penultimo massimo è 8, quindi 8 è maggiore di 2? sì, vero, quindi 1!)

Praticamente serve solo quando il risultato che vogliamo valutare è tra true o false, stringa nulla o meno, ecc.

A questo si aggiunge il null coalescing operator che integra il controllo della nullità della variabile, sostituendosi alla funzione isset. Immaginiamo di avere:

Questo può diventare ora:

Il comportamento è identico. Il risultato è che le seguenti due scritture sono fondamentalmente uguali, eccetto per un dettaglio:

La prima non produce una notice, mentre la seconda ci segnala qualcosa del tipo:

Notice: Undefined index: valore in index.php on line 9

Facciamo un altro esempio con entrambe:

La prima scrittura restituisce Mario senza ulteriori errori, l’oggetto non è dichiarato, quanto l’attributo; la seconda produce ancora due notice:

Notice: Undefined variable: studente in index.php on line 15

Notice: Trying to get property 'nome' of non-object in index.php on line 15

A questo punto potremmo anche scrivere:

Per dichiarare l’oggetto laddove inesistente, mentre la seguente scrittura produrrebbe sempre una notice:

A questo punto potremmo scrivere altre due equivalenze, dal punto di vista del risultato:

Ovviamente possiamo sfruttare l’operatore per altre aggregazioni del tipo:

Dove il risultato è 42, ovvero il primo valore non null della sequenza.

4. Virgola finale negli argomenti di funzione

Adesso è possibile dimenticarsi una virgola dopo l’ultimo argomento di una funzione, senza che il PHP si agiti per questo 🙄

Mentre sia nel PHP 5 che nel PHP 7 la seguente dicitura non provocava problemi:

Provare a fare lo stesso con una funzione, che accetti argomenti predefiniti o meno, provoca un errore:

Nel PHP 5 entrambe le funzioni avrebbero prodotto un errore del tipo:

Parse error: syntax error, unexpected ')' in index.php on line 12

Personalmente non la trovo un’innovazione strepitosa, ma va bene, adesso sappiamo che c’è.

5. Migrazione a PCRE2

Il PHP utilizza in generale PCRE per l’interpretazione delle espressioni regolari. Nel PHP 7.3 è stato finalmente introdotto l’utilizzo del PCRE2 che ha aspetti un po’ più stringenti e severi sulla sintassi. Facciamo un esempio, immaginando di avere una stringa dalla quale vogliamo trovare tutte le parole, compreso il simbolo (meno) e il . (punto); nel PHP 5 entrambe le seguenti scritture sarebbero state valide:

Soprassediamo sul fatto che i caratteri speciali verranno saltati e considerati alla stregua di spazi, ma il risultato sarà qualcosa di simile a:

 

Usando la prima espressione regolare all’interno di un programma come il Notepad++ avremmo ottenuto un errore:

Mentre la seconda è valida. Adesso anche nel PHP 7.3 la seconda espressione è l’unica valida, mentre la prima non funziona producendo un errore del tipo:

Warning: preg_match_all(): Compilation failed: invalid range in character class at offset 3 in index.php on line 10

Giusto per curiosità, se si volessero prendere anche i caratteri speciali potremmo utilizzare la seguente espressione regolare:

6. Unicode Codepoint Escape Syntax

Visto che si parla di stringhe facciamo un piccolo appunto a proposito dei riferimenti ai caratteri Unicode. Adesso è possibile specificarli direttamente nelle stringhe di testo con la sintassi \u{XXX}. Maggiori approfondimenti si possono trovare qui sul sito ufficiale. Questo significa che scrivendo:

Nel PHP 5 vedremo la stringa tale e quale:

\u{202E}Testo inverso

Mentre nel PHP 7 vedremo:

‮Testo inverso

Il carattere in questione è il U+202E RIGHT-TO-LEFT OVERRIDE

Si possono usare tutti i caratteri unicode, anche quelli associati agli smile, per cui echo "\u{1F602}"; produrrà 😂

7. Chiamata di errore nella codifica JSON

Adesso è finalmente possibile forzare il JSON a sollevare un errore in caso di stringhe non (de)codificabili. E’ possibile infatti scrivere nel modo seguente:

Senza l’aggiunta di JSON_THROW_ON_ERROR non ci sarebbe nessuna segnalazione di errore. Grazie a tale istruzione otteniamo invece il seguente errore fatale:

Fatal error: Uncaught JsonException: Syntax error in index.php:8 Stack trace: #0 index.php(8): json_decode('stringa JSON no...', NULL, 512, 4194304) #1 {main} thrown in index.php on line 8

8. Exceptions per i fatal errors

A proposito di errori, finalmente è stato migliorato il sistema di cattura delle eccezioni con try… catch. Primo era sostanzialmente, per farla breve, necessario chiamare throw new Exception(); per sollevare un’eccezione. Adesso è possibile intercettare anche le eccezioni di sistema. Nel caso precedente l’eccezione è intercettabile con:

Come altro esempio immaginiamo di chiamare una funzione non esistente:

Nel dobbiamo usare Error per intercettare l’errore, e mentre nel PHP 5 avremmo comunque avuto il seguente output:

Fatal error: Call to undefined function funzione() in index.php on line 9

Mentre nel PHP 7 avremmo il seguente valore, prodotto dal nostro echo:

errore: Call to undefined function funzione()

9. Classi anonime

Tra le varie novità vi è la possibilità di implementare classi anonime. Cominciamo dall’esempio più semplice:

Nel PHP 5 questo produrrebbe un errore del tipo:

Parse error: syntax error, unexpected 'class' (T_CLASS) in index.php on line 7

Alla classe anonima possono essere passati anche degli argomenti per il costruttore, nel modo seguente:

L’output invece che Mario sarà Luigi. Le classi anonime possono anche estendere altre classi, come ad esempio:

Oppure implementarle:

Senza implementare il metodo stampaNome() avremmo il seguente errore:

Fatal error: Class class@anonymous contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Studente::stampaNome) in index.php on line 11

10. Dichiarazione del tipo di dato restituito

Il PHP 7 introduce la possibilità di forzare il tipo di dato restituito da una funzione. Immaginiamo di voler scrivere una funzione somma che restituisca solamente valori interi. Nella maniera classica avremmo scritto:

Passando come argomento 2.5 e 3 il risultato sarebbe stato 5.5, un float. Per forzare l’output di un intero avremmo potuto scrivere:

In PHP 7 è possibile anche scrivere:

Sintassi che nel PHP 5 avrebbe prodotto il seguente errore:

Parse error: syntax error, unexpected ':', expecting '{' in index.php on line 7

11. Metodo is_countable()

In PHP 7 è possibile verificare se un oggetto sia “conteggiabile” ovvero sia del tipo Countable. Immaginiamo la seguente serie di istruzioni:

Essendo Studenti conteggiabile viene stampato il conteggio. Nel PHP 5 avremmo ovviamente avuto un errore del tipo:

Fatal error: Call to undefined function is_countable() in index.php on line 19

Facciamo un altro esempio di funzione implementabile su Countable e dove ci può tornare utile il nuovo metodo:

In questo caso non abbiamo bisogno di chiamare la funzione count() all’interno di public function count(), ma possiamo tenere traccia della quantità di voci aggiunte al vettore $studenti tramite un contatore interno.

12. Primi e ultimi valori e chiavi di un array

Immaginiamo di avere un array di questo tipo:

Alla maniera precedente avremmo potuto scrivere:

In questo modo avremmo ottenuto un output del genere:

primo valore: 1
prima chiave: a
ultimo valore: 100
ultima chiave: c

Questo implica anche che stiamo spostando il cursore nella posizione attuale dell’array. Se provassimo a scrivere:

Il risultato non sarebbe corretto e avremmo:

primo valore: 1
ultimo valore: 100
prima chiave: c
ultima chiave: c

Quindi questa scrittura sarebbe stata impossibile. Ora, con il PHP 7.3 è possibile scrivere nel modo seguente:

Le funzioni proposte sono attualmente: array_key_first(), array_key_last() and array_value_first(), array_value_last() anche se sono state introdotte, nel PHP 7.3 solamente quelle riguardanti le chiavi. Maggiori dettagli sulla questione qui: PHP RFC: array_key_first(), array_key_last() and array_value_first(), array_value_last()

13. Il metodo Closure->call

Nel PHP 7 viene introdotta una semplificazione nell’atto di binding delle closure.

 

Se sembra che tutti si stia dicendo cose a caso vediamo un esempio:

Notiamo che la funzione scritta su $closure va ad integrare la classe, potendo interagire con tutte le sue variabili interne anche se private.

14. Prestazioni migliorate

Infine il PHP 7 introduce notevoli implementazioni in termini di performance. Di seguito riporto i risultati di benchmark ottenuti grazie a benchmark-php su un medesimo server, ma con due diverse versioni di PHP. In particolare la versione PHP 7.3 introduce notevole stabilità nell’esecuzione e nel mantenimento delle performance.

PHP 7.3.5 PHP 5.6.40

 

Vedi articolo

Installare Ubuntu 19.10 con webserver pronto all’uso [per esordienti assoluti]

Abbiamo già visto come installare Ubuntu 18.04.2 LTS e Ubuntu 16.04.2 LTS predisponendoli per fare da webserver. Oggi voglio ripetere la procedura con Ubuntu 19.10.

Prima di andare avanti vorrei far notare come questa non sia una versione LTS, ossia una distribuzione con supporto a lungo termine, quindi ne sconsiglio caldamente l’installazione per progetti di lunga portata.

Detto ciò proseguiamo come di consueto utilizzando VirtualBox ai fini di questa guida, benché la procedura sarebbe analoga per chiunque lo volesse installare su una macchina fisica.

Gli argomenti trattati saranno:

  1. Configurazione ed installazione Ubuntu Server 19.10
  2. Installazione e configurazione Apache
  3. Installazione e configurazione MySQL
  4. Installazione e configurazione PHP
  5. Installazione di phpMyAdmin
  6. Ulteriori configurazioni

1. Configurazione Ubuntu Server 19.10

Anzitutto andiamo sul sito ufficiale di Ubuntu e procuriamoci la ISO per l’installazione. Assicuriamoci di selezionare la versione server e poi premiamo download:

A questo punto andiamo a creare la nostra macchina virtual con VirtualBox. All’interno di VirtualBox premiamo su CTRL+N per avviare l’installazione di una nuova macchina.

Diamo un nome alla macchina e scegliamo eventualmente il percorso di installazione, come nell’immagine di sopra. Assicuriamoci anche che il tipo sia settato su Linux e la Versione su Ubuntu (64-bit). Premiamo su Successivo.

Selezioniamo la quantità di memoria da destinare alla macchina virtuale (1GB è più che sufficiente). Ancora Successivo.

Lasciamo l’opzione selezionata Crea subito un nuovo disco fisso virtuale per crearne uno nuovo e andiamo avanti.

Se non abbiamo esigenze specifiche lasciamo il tipo di disco su VDI e procediamo avanti.

Lasciamo l’allocazione del disco su Allocato dinamicamente. In questo modo il disco crescerà solo in presenza di file effettivi, occupando meno spazio sulla macchina ospite. Andiamo avanti.

Diamo un po’ di spazio ad Ubuntu, visto che comunque andrà ad occupare solo quello necessario, mettendo il disco su 20GB.

A questo punto nell’elenco delle nostre macchine virtuali vedremo comparire quella con Ubuntu.

Una volta selezionata spostiamoci in alto e clicchiamo sul tasto verde Avvia per farla partire.

Al primo avvio ci verrà chiesto se caricare una ISO per l’avvio della macchina virtuale. Clicchiamo sulla cartellina gialla e poi selezioniamo la ISO che abbiamo scaricato in precedenza, se abbiamo fatto tutto bene, prima di procedere avanti, vedremo una situazione simili alla seguente:

Aspettiamo che compaia la sezione della selezione della lingua. Tanto per cambiare manca l’italiano, perciò proseguirò in inglese (o per fare uno scherzo proseguo in croato!).

Premiamo INVIO. Ci potrebbe chiedere se vogliamo aggiornare l’installer, diciamo di sì premendo di nuovo INVIO.

Adesso ci verrà chiesto il layout della tastiera. Dal momento che sto usando una tastiera italiana dovrò impostare il layout su Italian, come nell’immagine in alto, altrimenti potrei avere problemi specialmente con i caratteri speciali. Per farlo mi sposto in alto con le frecce direzionali e seleziono il menu premendo SPAZIO. Una volta trovata la voce giusta premo nuovamente INVIO. Dopodiché posso tornare alla voce Done e premere INVIO per procedere.

Mi verrà chiesto di configurare la rete, posso premere nuovamente INVIO e andare avanti.

Sulle impostazioni del proxy, a meno di non essere a conoscenza di diversa configurazione, lascio tutto com’è e premo INVIO.

L’indirizzo del mirror per la repository lo posso lasciare tale e quale, premendo ancora INVIO.

Alla voce successiva seleziono la seconda opzione, quella di configurazione dell’intero disco con utilizzo di LVM. Per approfondimenti sull’argomento consiglio LVM, gestore logico dei volumi su Ubuntu [per pinguini alle prime armi]

Mi verrà chiesto quale disco utilizzare, avendone uno soltanto non ho molto da scegliere, in caso contrario potrei selezionare il disco sul quale intendo installare le partizioni principali del server.

A questo punto mi verrà proposto un riassunto di tutte le modifiche che saranno applicate al disco. Se non ho altre esigenze posso premere INVIO e procedere.

Comparirà un avviso che mi segnalerà che l’intero contenuto del disco adesso verrà cancellato e sostituito con la nuova installazione; mi sposto con le frecce direzionali su Continue e premo INVIO.

Adesso inseriamo il nostro nome, scegliamo un nome per il server e username e password, compilando i campi come di seguito.

Una volta compilati tutti i campi premiamo INVIO.

A questo punto ci viene chiesto se vogliamo installare anche il server OpenSSH, che ci permetterà di collegarci in SSH al nostro server. Premiamo la SPAZIO per selezionare l’opzione e poi premiamo INVIO. Prima di premere invio la configurazione dovrebbe apparire come la seguente.

Saltiamo la selezione di snaps per il server (ovvero configurazioni preconfezionate, come viene spiegato alle singole voci). Spostiamoci in basso e selezioniamo semplicemente Done e poi premiamo INVIO.

Se abbiamo fatto tutto bene comincerà un’installazione come la seguente:

Una volta terminata ci verrà chiesto di riavviare il sistema e rimuovere il supporto di installazione. Premiamo semplicemente INVIO.

Se ci dovessero essere problemi con l’unmounting del cdrom, e dovesse comparire una schermata come quella di seguito, sarà sufficiente premere INVIO un’altra volta per dire al sistema di procedere comunque (VirtualBox avrà già smontato l’ISO per conto suo probabilmente).

A questo punto ci si dovrebbe trovare di fronte ad una schermata simile alla seguente:

Faccio notare che continua a persistere il ridicolo problema delle ultimissime versioni di Ubuntu, per cui la schermata di login appare prima che sia terminato il processo di avvio, cosa che riempie la shell di output anche dopo l’apparizione del prompt di ingresso.

Per effettuare il login sarà sufficiente premere nuovamente INVIO e poi digitare il nome utente e la password che abbiamo creato in precedenza.

Adesso, prima di procedere, voglio configurare la scheda di rete di VirtualBox, in modo da poter utilizzare Putty per collegarmi alla macchina virtuale. Lo faccio principalmente per poter copiare ed incollare i comandi sul terminale, cosa non possibile dall’interfaccia di VirtualBox stesso.

Per spegnere il sistema operativo digitiamo quindi:

Una volta spenta la macchina virtuale torniamo sull’interfaccia di VirtualBox e andiamo su File > Preferenze (che possiamo aprire anche premendo CTRL+G)

Andiamo su Rete e clicchiamo sul piccolo pulsante della scheda con il più verde sulla destra che ci permetterà di creare una nuova Rete con NAT da far utilizzare alla nostra macchina virtuale.

Configuriamo la rete nel modo seguente:

Clicchiamo su Inoltro del porte e configuriamo le porte da inoltrare dalla scheda di rete virtuale sul nostro computer alla rete interna di VirtualBox.

Configuriamo l’inoltro delle seguenti porte:

 

Stiamo dando per scontato che la macchina virtuale si troverà all’indirizzo 10.0.2.4 della rete interna (che è tipicamente l’indirizzo predefinito che viene assegnato dal DHCP di VirtualBox).

Detto questo premiamo OK su tutte le finestre aperte e torniamo alla nostra macchina virtuale. Dopo averla selezionata premiamo il tasto Impostazioni (vicino a quello di Avvio).

Dalla schermata delle Impostazioni andiamo su Rete e selezioniamo Rete con Nat, scegliendo dal menu sottostante la Rete Ubuntu che abbiamo creato prima.

Fatto tutto questo premiamo OK e avviamo di nuovo la nostra macchina virtuale. Una volta che sarà ripartita apriamo Putty e digitiamo come indirizzo di connessione 192.168.56.1

Premiamo OK. Se abbiamo fatto tutto correttamente ci verrà chiesto di effettuare la connessione.

Apparirà una schermata che ci chiederà di copiare la chiave di crittografia. Premiamo .

Inseriamo le credenziali e siamo pronti a procedere oltre.

2. Installazione e configurazione Apache

Adesso procediamo con l’installazione di Apache. Aggiorniamo anzitutto tutti i riferimenti della repository digitando:

Dopodiché digitiamo:

Alla domanda se proseguire digitiamo Y e poi premiamo INVIO. Aspettiamo che l’installazione termini. Se tutto è andato bene aprendo l’indirizzo http://192.168.56.1/ dal nostro browser dovremmo vedere la schermata predefinita del webserver Apache nel modo seguente:

3. Installazione e configurazione MySQL

Adesso installiamo il Server MySQL per il database. Per farlo digitiamo:

Come al solito confermiamo l’installazione con Y e aspettiamo che sia terminata.

Una volta terminata l’installazione digitiamo:

Questo avvierà una procedura di configurazione del nostro database, durante la quale ci verranno richieste diverse cose. Alle varie domande rispondiamo rispettivamente:

Press y|Y for Yes, any other key for No: Y

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2

(dove: STRONG Length >= 8, numeric, mixed case, special characters and dictionary file)

New password: 4y!7dz=6/%lF-4fes2=lkpl|E^DTL*  (questo è un esempio di password che possiamo mettere, questa password ha una qualità di 180bit e una lunghezza di 30 caratteri)

Se la passowrd è buona ci verrà detto qualcosa come:

Estimated strength of the password: 100

Proseguiamo:

Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : Y

Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y

Fatto questo il database è pronto per essere utilizzato.

L’utente predefinito del database sarà root e la password quella che abbiamo scelto prima.

4. Installazione e configurazione PHP

Adesso installiamo il PHP, aggiungendo la libreria per Apache e quella per il database MySQL.

Faccio notare che in questo modo verrà installato l’ultimo PHP disponibile, che nel mio caso specifico, come si può vedere anche dall’immagine di seguito, è il PHP 7.3.

Una volta installato il PHP verifichiamo che sotto Apache siano configurate le pagine predefinite come index.php per l’esecuzione. Digitiamo:

Se va tutto bene sotto la voce DirectoryIndex dovremmo trovare, tra gli altri file, anche index.php. Se così non fosse lo aggiungiamo come nell’immagine seguente:

Nel caso avessimo modificato il file salviamo il tutto premendo CTRL+O, altrimenti direttamente CTRL+X per uscire dall’editor.

Fatte tutte queste belle cose riavviamo Apache.

5. Installazione di phpMyAdmin

Per installare il phpMyAdmin utilizzeremo il composer, per cui installiamolo digitando:

Il composer è uno strumento per la gestione delle dipendenze e delle librerie del PHP, che ci permette di installare progetti in PHP come è per l’appunto il phpMyAdmin.

A questo punto installiamo il minimo indispensabile per usare il phpMyAdmin digitando:

Riavviamo Apache digitando come al solito:

Fatto tutto questo possiamo procedere con l’installazione vera e propria. Spostiamoci anzitutto dentro a /var/www:

Assegniamo il nostro utente alla cartella html (che è la cartella predefinita del nostro webserver raggiungibile dall’indirizzo di prima):

Entriamo dentro con:

A questo punto installiamo qui il nostro phpMyAdmin, che creerà una sua cartella alla quale assegneremo successivamente Apache come utente. In realtà la cartella del phpMyAdmin potrebbe essere creata a nostro piacimento in qualsiasi posizione, purché abbia un senso per noi. Tradizionalmente viene inserito sotto etc oppure share. Io l’ho inserito direttamente sotto www per una questione di ordine. (Qualora la si dovesse mettere altrove dovremmo ricordarci di aggiungere il percorso anche ai VirtualHost)

ATTENZIONE! composer non va lanciato come root/super user, quindi non va utilizzato sudo anteposto al commando. 

Aspettiamo con pazienza l’esito dell’installazione che potrebbe richiedere qualche minuto, soprattutto all’inizio quando non sembra succedere niente di che. Se tutto è andato bene vedremo un output come quello di seguito.

In caso di errore assicuriamoci di aver installato tutte le librerie per il PHP come di sopra e di aver riavviato Apache.

Prima di testare il phpMyAdmin così installato ripristiniamo sulla cartella html l’utente predefinito di Apache digitando:

A questo punto digitiamo nel browser http://192.168.56.1/phpmyadmin/

Se abbiamo fatto tutto bene dovremmo vedere qualcosa come questo:

Provando ad inserire root e la password creata in precedenza potremmo incorrere nel seguente errore:

Nessun problema. Torniamo sul terminale e digitiamo:

Inseriamo la password creata in precedenza per l’utente root. (per capirsi nel mio caso la password era 4y!7dz=6/%lF-4fes2=lkpl|E^DTL*)

Creiamo un utente apposito per gestire il database da phpMyAdmin. Per farlo eseguiamo la seguente sequenza di query:

L’utente così creato sarà:

username: admin

password: HGOqXovUhyZJ4}08}eg-lAiOM])}@lYt

Proviamo ad accedere con tali dati da http://192.168.56.1/phpmyadmin/

Nel caso dovesse apparire l’errore mysqli::real_connect(): The server requested authentication method unknown to the client [caching_sha2_password] eseguiamo i seguenti due comandi sul database.

Se è andato tutto bene possiamo riprovare ad accedere e vedremo una situazione simile a questa.

6. Ulteriori configurazioni

A questo punto abbiamo finito la configurazione principale e dovremmo fare ancora qualche implementazione, configurando cose come:

  1. Sistemare il Firewall
  2. Mettere in sicurezza Apache
  3. Configurare fail2ban ed altri eventuali servizi
  4. Aggiungere un VirtualHost al webserver
Vedi articolo

[CentOS] Prima installazione e configurazione base per webserver (LAMP, fail2ban)

Oggi ho deciso di cimentarmi nell’installazione di quel obbrobrio modaiolo che è CentOS. Dico così perché è a tutti gli effetti utilizzato da meno del 20% dei webserver ed in generale mi sono convinto che venga scelto più per una questione di moda, che per qualche reale vantaggio rispetto ad Ubuntu/Debian.

Fonte w3techs.com

Lungi dal voler scatenare una guerra tra distribuzioni, questo resta naturalmente un mio personalissimo parere, corroborato da “qualche” statistica (cioè non toglie, che io stesso, in momenti di malignità, abbia installato CentOS, per il morboso gusto dell’esperimento sulla pelle d’altri).

Comunque sia avventuriamoci in questo mondo e vediamo un po’ di differenze rispetto ad Ubuntu e Debian.

Come al solito utilizziamo VirtualBox e putty, mentre per scaricare la ISO è sufficiente andare sul sito ufficiale.

1. Installazione

Anzitutto ci viene chiesto che cosa intendiamo fare, scegliamo la prima opzione (banalmente premiamo INVIO, oppure I) e proseguiamo.

A questo punto compare una schermata con interfaccia grafica dove scegliere la lingua di installazione.

Scegliamo l’italiano come nella figura seguente e poi proseguiamo.

Selezioniamo Continua e ci troviamo di fronte alla schermata di tutte le impostazioni possibili.

Notiamo come è segnalato un “problema” sulla destinazione dell’installazione, unica cosa che dobbiamo scegliere effettivamente. Tutti gli altri parametri sono preconfigurati nella versione minima predefinita e possiamo lasciarli tali. Clicchiamo quindi su destinazione di installazione.

Scegliamo il nostro disco (nel mio caso quello da 30GB) e lasciamo la configurazione automatica (come avremmo fatto per Ubuntu). Clicchiamo su FATTO.

Adesso è possibile scegliere Avvia installazione.

Mentre prosegue l’installazione, con tanto di banner pubblicitario non richiesto (e questo già la dice lunga su dove ci stiamo avventurando) possiamo configurare la password di root ed eventuali altri utenti. In questo caso creiamo soltanto il nostro utente root dandogli una password. Clicchiamo su password di root.

Se si trattasse di una vera installazione online ci converrebbe, naturalmente, scegliere una buona password. Io ne metto una semplice, che però non sia troppo semplice e venga accettata. Il fatto stesso che il sistema “protesti” all’inserimento di “password” è un altro dei punti che trovo detestabili, visto che ho scelto linux proprio per fare, e sbagliare anche, di testa mia. Ma procediamo. Io ho messo una password un po’ più complessa, anche se si tratta di un esempio.

Quando l’installazione è completata possiamo riavviare il sistema.

Adesso possiamo cominciare a lavorare.

2. Connessione in SSH e configurazione rete

Se avete scelto l’installazione minima prima di potersi collegare in SSH, dopo aver inoltrato le porte su VirtualBox, qualora stesse lavorando sotto NAT come sto facendo io, è necessario avviare il servizio di rete. Per farlo digitiamo:

Senza questo servizio avviato non ci si può nemmeno collegare a internet.

Apriamo putty (o il nostro client ssh) e colleghiamoci normalmente alla macchina che abbiamo appena installato.

A questo punto impostiamo la rete perché si avvii automaticamente ad ogni riavvio del sistema (altrimenti dovremmo farlo noi a mano). Per poter modificare il file avremo bisogno di un editor di testo, quindi installiamo nano (ce ne sono anche tanti altri):

Ci verrà chiesto di confermare l’installazione e sarà sufficiente premere y o s, in base a quello che viene proposto.

Fatto questo identifichiamo la nostra scheda di rete, ifconfig non funziona perché andrebbe installato, quindi digitiamo:

Nel mio caso vengono mostrate le seguenti due schede:

Faccio notare che la prima interfaccia di rete è quella locale, chiamata lo, mentre la seconda è la scheda di rete della macchina virtuale (in una configurazione su macchina fisica qui avremmo eth0 probabilmente) chiamata enp0s3.

Da qui possiamo anche vedere che alla scheda di rete è stato assegnato l’indirizzo IP 10.0.2.15 (classica configurazione di VirtualBox).

Quindi andiamo a vedere i file di configurazione di rete e digitiamo:

Questo ci mostrerà vari file di configurazione, come nella schermata seguente:

Notiamo i primi due file che hanno i nomi ifcfg-enp0s3 e ifcfg-lo. Modifichiamo quindi il file di configurazione della scheda di rete:

Ci dovremmo trovare di fronte a qualcosa di simile a questo:

Modifichiamo il parametro ONBOOT=no facendolo diventare ONBOOT=yes. Salviamo premendo CTRL+O e riavviamo il computer per accertarci che sia tutto andato bene.

Per riavviare digitiamo:

Se tutto è andato bene potremo accedere normalmente in SSH.

3. Installazione server LAMP

Adesso è il momento di installare il nostro server LAMP (Linux + Apache + MySQL + PHP). Anzitutto digitiamo:

Una volta completata l’installazione dobbiamo avviare il servizio e configurare il firewall perché sia accessibile.

Quindi per avviare il servizio digitiamo:

Mentre per configurare il firewall utilizziamo firewall-cmd digitando:

Faccio notare che quello che viene configurato sono 2 servizi, ovvero due porte, HTTP 80, HTTPS 443.

Andando all’indirizzo http://192.168.56.1/ (questo è il mio indirizzo della macchina virtuale) possiamo verificare che il server web funzioni correttamente (apparirà una pagina con scritto Testing 123…)

Adesso dobbiamo installare MySQL / MariaDB, MariaDB è l’evoluzione del MySQL, compatibile con quest’ultimo. Nel nostro caso installiamo MariaDB (giusto per variare un po’ sul tema, per il MySQL la procedura è analoga). Quindi digitiamo:

Faccio notare che il flag -y permette di installare tutto senza ulteriori richieste di conferma. In modo analogo a prima digitiamo poi:

In questo modo abilitiamo ed avviamo il servizio. Adesso però dobbiamo impostare la password dell’utente principale del database, che si chiama sempre root, anche se è diverso dal root di sistema. Oltre a questo vogliamo configurare alcuni parametri di sicurezza. Digitiamo:

Verranno poste le seguenti domande:

  1. Enter current password for root (enter for none): PREMIAMO INVIO, non c’è nessuna password di root per ora
  2. Set root password? [Y/n]: Y
  3. New password: METTIAMO UNA PASSWORD
  4. Re-enter new password: RIPETIAMO LA SUDDETTA PASSWORD
  5. Remove anonymous users? [Y/n] Y
  6. Disallow root login remotely? [Y/n] Y
  7. Remove test database and access to it? [Y/n] Y
  8. Reload privilege tables now? [Y/n] Y

In questo modo abbiamo messo in sicurezza e configurato il nostro database.

Adesso è il turno del PHP. Per assicurarci di scaricare la versione più recente, ovvero il PHP7, aggiorniamo la repository.

A questo punto digitiamo:

Questo installerà il PHP7.0.

A questo punto comincia una piccola avventura degna solo di CentOS. Anzitutto bisogna abilitare il PHP affinché venga eseguito dal motore php-fpm (il PHP è un linguaggio compilato sul momento e può essere eseguito da diversi motori). Per qualche ragione l’installazione con yum non si occupa di questa cosa. Spostiamoci quindi in /etc/httpd/conf.d/ dove andremo a creare un file di configurazione chiamato fpm.conf. Attenzione, nel nome non c’è niente di speciale, poteva anche essere ilmiophp.conf. L’importante è l’estensione *.conf. Digitiamo quindi:

In questo modo reindirizziamo le richieste dei documento PHP al server fcgi.

A questo punto dobbiamo avviare il servizio e riavviare Apache, digitando la seguente serie di comandi:

Eventualmente, se avessimo bisogno, possiamo visualizzare lo stato del servizio fpm-php digitando:

A questo punto creiamo la nostra solita pagina PHP di prova in /var/www/html (stesso percorso predefinito di Ubuntu):

Dentro il file incolliamo:

Salviamo premendo come al solito CTRL+O.

Adesso apriamo la nostra pagina web al solito indirizzo di prima http://192.168.56.1/. Quello che vediamo, per la nostra massima felicità, è quanto segue:

Questo dipende dal fatto che abbiamo creato il file index.php come root, e non gli abbiamo assegnato l’utente di Apache. Per farlo anzitutto controlliamo l’utente con cui gira Apache aprendo:

Scendendo nel file vedremo una voce simile a questa:

In questo caso (ma è così di solito) il nostro utente è apache ed il gruppo è apache. Quindi modifichiamo i permessi sul file appena creato:

A questo punto ricontrolliamo e scopriamo due cose:

1. l’errore si presenta uguale a prima

2. la guida di CentOS stesso fa totalmente schifo. Le istruzioni da incollare dentro ad fpm.conf le ho infatti copiate da qui, quello che però non viene detto è che andrebbe anche configurato index.php come pagina predefinita, altrimenti apache pensa che, non essendoci una index.html, non si possa accedere alla cartella

Quindi digitiamo:

E modifichiamo il file di prima in modo tale che risulti così (ho aggiunto solo l’ultima riga):

A questo punto riavviamo Apache:

E il risultato che otteniamo collegandoci a http://192.168.56.1/ dovrebbe essere così:

Controllando la pagina web precedente vedremo che non è installata l’estensione per gestiore MySQL/MariaDB. Per farlo è sufficiente digitare:

Una volta fatto riavviamo il servizio FPM PHP.

Adesso però verifichiamo se è andato davvero tutto bene collegandoci anche al database. Anzitutto creiamo un nuovo database.

Per farlo accediamo al MySQL/MariaDB che abbiamo installato prima. Digitiamo:

Attenzione! La medesima istruzione va digitata anche nel caso che si stia usando MariaDB, come sto facendo io, che vi ricordo è un aggiornamento di MySQL perfettamente retrocompatibile.

Digitiamo la password del database e ci troviamo nella console di gestione di MariaDB, che appare così:

Questo significa che non abbiamo selezionato alcun database. Adesso creiamo un database (io lo chiamerò petar):

Proviamo anche a creare un utente chiamato petar e che possa accedere a tale database solamente da localhost (quindi da connessione locale). Per farlo digitiamo:

La password per il nuovo utente sarà password123. Per uscire dalla console del MariaDB digitiamo:

Adesso torniamo sul nostro file /var/www/html/index.php di prima e modifichiamolo nella maniera seguente:

Se abbiamo fatto tutto bene andando su http://192.168.56.1/ vedremo qualcosa di simile a questo:

In caso che ci sia stato qualche errore (possiamo riprodurlo di proposito sbagliando la password nel suddetto codice php) dovremmo vedere qualcosa di simile:

Accertiamoci anche che, modificando il codice in questo modo:

Nella suddetta pagina appaia la seguente sezione dedicata al MySQL.

Se per qualunque ragione non dovesse esserci la libreria non è installata correttamente.

4. Configurazione Firewall

A questo punto controlliamo lo stato del firewall. Vediamo anzitutto alcuni comandi utili.

Per accertarci che sia attivo digitiamo:

A questo punto controlliamo lo stato della configurazione digitando:

Dovremmo vedere qualcosa di simile a questo:

Notiamo che l’interfaccia del firewall è su enp0s3 (la nostra unica scheda di rete, su una macchina fisica tipicamente eth0).

I servizi attivi sono invece ssh dhcpv6-client http https. Ricordiamoci che queste ultime due le abbiamo configurate al punto 3 precedente.

Come già detto, quindi, per aggiungere un nuovo servizio al firewall è sufficiente digitare:

Mentre per rimuoverlo, ad esempio rimuovere il servizio http, basta digitare:

In entrambi i casi, affinché le modifiche abbiano successo, è necessario riavviare il firewall:

Tutto questo è molto bello, ma sinceramente preferisco lavorare con iptables. Ricordiamoci che sia firewalld che iptables sono due software, distinti, che gestiscono il firewall vero che si chiama netfilter. Per verificare che sia installato, dovrebbe esserlo, digitiamo:

Il risultato dovrebbe essere qualcosa come: iptables-1.4.21-18.2.el7_4.x86_64

Questo ci indica l’ultima versione installata. Controlliamo quindi, con iptables, qual’è la configurazione attuale.

Quello che viene fuori è un casino simile a questo:

Personalmente trovo tragicomico che un’installazione minima di CentOS parta con una simile configurazione di iptables (e soprattutto parta con aperta solamente la porta SSH). Essendo un’installazione minima ci si potrebbe aspettare che il firewall non sia configurato e che tutte le porte siano aperte, per poi dovercene occupare noi.

Per tanto, siccome voglio avere una visione chiara della situazione del firewall, resetto tutto quanto impostando aperte solo le porte per SSH, HTTP e HTTPS. Per farlo mi è sufficiente eseguire il seguente codice da terminale (va bene anche un copia/incolla)

Per approfondimenti suggerisco: Lavorare con iptables su Ubuntu [per pinguini in erba]

Il risultato di questa purga, digitando iptables -L, dovrebbe essere così:

Per salvare la configurazione dobbiamo installare i servizi di iptables digitando:

Abilitiamo il servizio digitando:

Già che ci siamo sbarazziamoci di firewalld:

Riavviamo il servizio iptables (fino ad ora abbiamo usato solo il programma client):

E infine salviamo:

A questo punto dovremmo ricevere una conferma di questo tipo:

Per accertarci che tutto sia andato bene possiamo riavviare l’intera macchina con un reboot now e ricontrollare lo stato del firewall digitando iptables -L.

5. Installazione di fail2ban

Come ultima operazione installiamo fail2ban, onde limitare le possibilità di ricevere attacchi sulla porta 22 del protocollo SSH. In questo modo evitiamo che si possano fare numerosi tentativi per scoprire i dati di accesso, bannando via via gli indirizzi IP da cui arrivano gli attacchi.

Per installare fail2ban anzitutto aggiungiamo il pacchetto EPEL Project alla nostra repository.

Qualora risultasse già installato tanto meglio. Procediamo installando fail2ban:

Completata l’installazione abilitiamo fail2ban digitando:

Adesso configuriamo il programma. Per farlo possiamo modificare alcuni file. In particolare teniamo presente le seguenti cose:

  1. /etc/fail2ban/jail.conf questo il primo file di configurazione, è quello predefinito, lo possiamo modificare, ma se vogliamo fare un lavoro pulito ci conviene lasciarlo così com’è
  2. /etc/fail2ban/jail.d/*.conf, questi sono i file *.conf predefiniti, vengono accorpati al file precedente, sostituendo eventuali parametri equivalenti, anche questi file possono essere lasciati intatti così come sono
  3. /etc/fail2ban/jail.local questo è il file di configurazione locale, segue ai due file precedenti, e quindi ogni modifica apportata qui dentro potrà sovrascrivere le precedenti
  4. /etc/fail2ban/jail.d/*.local, infine questa è la cartella nella quale si troveranno i file *.local personalizzati che andranno a sostituire quelli precedenti e verranno accorpati in ordine alfabetico

Quindi anzitutto impostiamo i parametri base per fail2ban modificando il seguente file:

Il file risulterà vuoto, quindi ci possiamo incollare dentro i seguenti parametri. Questi andranno a sostituire quelli di default.

A questo punto creiamo un file per l’SSH digitando:

Ricordiamoci che i file verranno letti in ordine alfabetico, nel nome del file, a parte l’estensione *.local, non c’è niente di speciale. Si poteva anche chiamare 001-config.local.

Salviamo e riavviamo fail2ban:

Verifichiamo la situazione digitando:

Ci dovrebbe comparire qualcosa di simile:

Notiamo che è abilitata una jail per l’sshd. Stessa verifica la possiamo fare su iptables digitando iptables -L e controllando la presenza di una chain per fail2ban.

Per accertarci che tutto vada bene possiamo tentare di accedere in SSH sbagliando password. Inutile dire che una volta bannati dovremo poter accedere direttamente alla macchina per sbannarci.

Per visualizzare gli ip bannati è sufficiente digitare (per la chain f2b-sshd creata fa fail2ban dentro al firewall):

In questo caso il mio IP è il 10.0.2.2 e possiamo notare che appare tra quelli bannati:

Per rimuoverlo, ovvero sbloccare l’indirizzo ip bannato, basta digitare:

A questo punto possiamo accedere nuovamente mediante SSH.

Adesso abbiamo configurato CentOS per essere pronto ed operativo come server LAMP.

Vedi articolo