Monitorare una pagina web con Raspberry Pi

Creiamo un sistema che ci consente di ricevere una mail quando una pagina web viene aggiornata.

Lo scopo di questo progetto è ricevere una mail quando una pagina web statica viene aggiornata e quindi cambia. Avremo bisogno di server web che ci consenta di inviare la mail sotto richiesta della Raspberry che controllerà la pagina continuamente rispettando un intervallo di tempo da noi specificato. La guida si divide quindi in due parti, il lato server che si occuperà di inviare la mail (cosa che può svolgere anche la raspberry ma in questa guida per semplicità utilizzo un dominio linux vero e proprio) e un lato locale rappresentato dalla raspberry in sé che controllerà la pagina. Iniziamo subito!

Lato server

Il nostro server deve inviare una mail non appena viene caricata una pagina che chiameremo mail.php. Potremmo utilizzare la funzione mail() in php ma la nostra mail verrebbe subito gettata nella posta indesiderata, utilizzeremo una libreria php vera e propra nota come PHPmailer che utilizzerà un server SMTP vero e proprio, per esempio quello della nostra casella di posta di Yahoo! (o di qualsiasi altra casella di posta vogliate, il nostro obiettivo è far si che la mail non cada nello spam)

  1. Scarichiamo l’archivio zip da GitHub nel link precedente, decomprimiamolo e carichiamo tutti i file sul server in una cartella phpmailer/ che si troverà all’interno di una cartella che chiameremo da ora raspberry/. Quindi la nostra libreria si troverà in http://ilmiosito.com/raspberry/phpmailer
  2. Ora in /raspberry creiamo un file denominato mail.php e scriviamo quanto segue, trovate sopra ogni riga la funzione corrispettiva:
    IsSMTP();
    // Settiamo il nomer del server SMTP (in questo caso è yahoo)
    $messaggio->Host ='smtp.mail.yahoo.com';
    $messaggio->SMTPAuth = true; // Attiviamo l'autenticazione del serve
    $messaggio->Port = 587; // La porta
    $messaggio->Username = '[email protected]'; // L'indirizzo mittente (username)
    $messaggio->Password = 'lamiapassword'; // e la password
    
    // Corpo della mail.
    // Settiamo su "true" se il corpo del messaggio sarà di tipo html
    $messaggio->IsHTML(true);
    // Settiamo il mittente
    $messaggio->setFrom('[email protected]', 'Giovanni Mela);
    // Settiamo il destinatario
    $messaggio->addAddress('[email protected]');
    // Impostiamo l'oggetto della mail
    $messaggio->Subject='Informazione sul sito';
    
    // Corpo del messaggio
    $messaggio->Body = "";
    $messaggio->Body .= "Ciao, ti volevo informare che il sito e' cambiato.";
    $messaggio->Body = "";
    
    // Invio del messaggio
    if(!$messaggio>Send()){
    echo $messaggio>ErrorInfo;
    }else{
    // Messaggio di conferma di avvenuto invio
    echo 'OK';
    }
    // Chiudi la connessione SMTP
    $messaggio->SmtpClose();
    unset($messaggio);
    ?>

    Ogni qualvolta accederemo all’indirizzo http://ilmiosito.com/raspberry/mail.php una mail verrà inviata all’indirizzo [email protected] da [email protected] sfruttando le credenziali di quest’ultimo indirizzo, nella pagina verrà visualizzato il messaggio “OK” se tutto è andato a buon fine. Il nostro server è pronto, passiamo alla raspberry!

Lato locale

Il file check_page_loop.sh

Dobbiamo controllare se una pagina web statica cambia nel tempo come possiamo fare velocemente? Calcoliamo l’impronta della sua sorgente e controlliamo se cambia, se cambia la pagina è diversa ed è stata quindi aggiornata con nuovi contenuti. Iniziamo quindi a scrivere il file check_page_loop.sh. Ci servirà il pacchetto w3m, se non è già installato installiamolo prima di continuare la guida (sudo apt-get install w3m)

  1. Impronta originale. Prima di avviare il ciclo otteniamo l’impronta attuale della pagina in questo modo:
    # Calculate hash before starting loop
    curl http://sito.com/pagina/ -s | w3m -dump -T text/html > page.txt
    cat page.txt | md5sum > stored_digest.txt
    rm -f page.txt

    La curl scarica la pagina e la w3m scrive l’output della pagina (non la sorgente, l’output è come visualizzata) nel file page.txt, la cat apre il file di cui viene calcolata l’impronta md5 e scritta nel file stored_digest.txt e infine viene cancellato il file temporaneo page.txt. Questa è l’impronta di riferimento che utilizzeremo per capire, in un ciclo, se la pagina ha subito variazioni, quindi immagazziniamola subito in una variabile chiamata STORED_DIGEST

    # Initialize stored digest
    STORED_DIGEST=$(cat stored_digest.txt)
  2. Il while. Ora possiamo avviare il ciclo while che principalmente compie la medesima azione del codice precedente ma immagazzina l’impronta in un’altra variabile:
    # Start loop
    while true; do
    # Get the page
    curl http://sito.com/pagina -s | w3m -dump -T text/html
    
    # Calculate checksum
    cat page.txt | md5sum > digest.txt
    rm -f page.txt
    
    # Initialize stored digest
    ACTUAL_DIGEST=$(cat digest.txt)
    rm -f digest.txt

    Le differenze con il codice precedente sono ovviamente la presenza del ciclo while (che verrà poi chiuso con l’istruzione done) e il fatto che la nuova impronta verrà immagazzinata in ACTUAL_DIGEST.

  3. Prendiamo una decisione. Ora confrontando le due impronte dobbiamo decidere se inviare la mail oppure no, con un if stabiliamo che se sono diverse -> invia mail altrimenti no:
    # Compare strings
    if [ "$STORED_DIGEST" == "$ACTUAL_DIGEST" ]; then
     echo "Fingerprint are EQUAL!"
    
    else
     echo "Fingerprint are NOT EQUAL!"
     wget -q http://ilmiosito.com/raspberry/mail.php
     rm -f mail.php
     break
    fi
    

    Per inviare la mail basta aprire la pagina creata in precedenza con la wget che ci salverà l’output in mail.php, file che possiamo eliminare e terminare con break il ciclo, quindi l’intero programma.

    4. Prendiamoci una pausa. Prima però di chiudere il ciclo facciamo passare un intervallo di tempo prima di controllare nuovamente la pagina, usiamo la sleep:

    # Sleep
    echo "Sleeping for 5 minutes"
    sleep 5m
    
    # End while
    done

    Vediamo il file conclusivo corredato di echo nel file log.txt

    #!/bin/bash
    
    # Automatically retrieve page and detect changes with mail server
    # by gabry3795 - gabry.gabry  hotmail.it for tuttodinternet.com
    
    echo "$(date) :: [ ] Starting new script" >> log.txt
    
    # Clean before start
    rm -f stored_digest.txt
    rm -f digest.txt
    rm -f page.txt
    
    # Calculate hash before starting loop
    curl http://sito.com/pagina -s | w3m -dump -T text/html > page.txt
    cat page.txt | md5sum > stored_digest.txt
    rm -f page.txt
    
    # Initialize stored digest
    STORED_DIGEST=$(cat stored_digest.txt)
    
    # Start loop
    while true; do
    
    echo "$(date) :: [ ] Starting new loop" >> log.txt
    
    # Get the page
    echo "$(date) :: [|| ] Getting page" >> log.txt
    curl http://sito.com/pagina -s | w3m -dump -T text/html > page.txt
    
    # Calculate checksum
    echo "$(date) :: [|||| ] Calculating checksum" >> log.txt
    cat page.txt | md5sum > digest.txt
    rm -f page.txt
    
    # Initialize stored digest
    echo "$(date) :: [||||| ] Initializing current digest" >> log.txt
    ACTUAL_DIGEST=$(cat digest.txt)
    rm -f digest.txt
    
    # Compare strings
    if [ "$STORED_DIGEST" == "$ACTUAL_DIGEST" ]; then
     echo "$(date) :: [|||||||] Fingerprint are EQUAL!" >> log.txt
    
    else
     echo "$(date) :: [|||||||] Fingerprint are NOT EQUAL!" >> log.txt
     echo "$(date) :: [|||||||] Sending mail..." >> log.txt
     wget -q http://ilmiosito.com/raspberry/mail.php
     rm -f mail.php
     break
    fi
    
    # Sleep
    echo "$(date) :: Sleeping for 5 minutes" >> log.txt
    sleep 5m
    
    # End while
    done

Il file start_daemon.sh

Ora dobbiamo avviare il programma in background magari via ssh e senza necessità di tenere il terminale aperto, sfruttiamo la funzione nohup che permette di avviare lo script senza che venga interrotto con CTRL+C. Scriviamo per comodità il comando nel file start_daemon.sh:

#!/bin/bash
nohup ./check_page_loop.sh &

Il file stop_daemon.sh

E anche il relativo file per fermare il programma, denominato stop_daemon.sh:

#!/bin/bash
killall check_page_loop.sh

Il file di log sarà log.txt ma comunque la funzione scrive automaticamente l’output in nohup.out

Conclusioni

Ora è tutto pronto, basterà connettersi via ssh alla raspberry e avviare lo script ./start_daemon.sh e premere CTRL+C, vedremo il file di log popolarsi e riceveremo una mail all’aggiornamento della pagina.