lunedì 2 aprile 2018

Verificare sync NTP con PHP su Raspberry Pi con Chrony

L'obiettivo di questo script è lo stesso di quello nel post precedente.

L'utilizzo di Chrony al posto di NTP su dispositivi come Raspberry Pi presenta il vantaggio di permettere uno slew rate maggiore e quindi poter sincronizzare l'orologio in tempi più rapidi senza salti che possano creare malfunzionamenti nelle funzioni di temporizzazione (cfr. maxslewrate e makestep nel manuale di chrony.conf).

Questo script è una variante del precedente che funziona con Chrony. Nel file, viene anche riportato il valore dell'errore tra l'ora di sistema e quella NTR al momento dell'acquisizione del sync, utile per far sapere all'applicazione di quanto è stato fuori sync l'orologio finora.

Chrony deve essere installato e configurato correttamente.

<?php

error_reporting
(E_ALL);

# Apro in scrittura il file su tmpfs
# se non esiste lo crea
$fhandle fopen("/mnt/pirun1/NtpSync""c");

# La scrittura dello stato avviene solo in caso di acquisizione
# o perdita del sync, per risparmiare risorse
# Lo stato del ciclo precedente viene salvato nella variabile:
$LastValue 2;
# Inizializzo a 2 in modo che poi, confrontata con 1 o 0 sia sempre falsa e
# faccia scrivere sempre il file temporaneo all'avvio dello script;

while (true) {
  
/*
   * Il comando waitsync è molto comodo per avere lo stato del sync del demone
   * vedere la pagina man di chronyc per i dettagli:
   * https://chrony.tuxfamily.org/doc/3.2/chronyc.html
   */

  
$LastLine exec("chronyc -n waitsync 10 0 0 0.1"$OutputArray$return_var);
  
/*
   * Variabile di ritorno è =0 se è in sync, !=0 se è fuori sync
   * Uso $LastLine per scrivere su $SystemError l'entità dell'errore
   */
  
if ($return_var === 0) {
    
$IsSynced 1;
    
preg_match('/correction: (.*), skew: /'$LastLine$LastLineErrorArray);
    
$SystemError $LastLineErrorArray[1] + 0;
  } else {
    
$IsSynced 0;
  }

  
# Se cambia lo stato, il file viene aggiornato.
  
if ($IsSynced <> $LastValue) {
    
fseek($fhandle0);
    if (
$IsSynced === 1) {
      
/*
       * Se mi interessa solo lo stato posso non acquisire il lock del file,
       * se serve anche l'errore è necessario farlo.
       */
      
fwrite($fhandle"1");
      
LogRow("In sync" PHP_EOL);

      
flock($fhandleLOCK_EX);
      
fwrite($fhandle"_err=" number_format($SystemError9) . "_");
      
flock($fhandleLOCK_UN);

      
$PollingInterval 1000000;
    } else {
      
fwrite($fhandle"0");
      
LogRow("Out of sync" PHP_EOL);
      
$PollingInterval 100000;
    }
  }
  
$LastValue $IsSynced;
  
usleep($PollingInterval);
}

function 
LogRow($text) {
  echo (
date("c") . " " $_SERVER["SCRIPT_NAME"] . " - " $text);
}

lunedì 26 marzo 2018

Verificare sync NTP con PHP su Raspberry Pi

Aggiornamento 02/04/2018: lo stesso script per il demone Chrony è a questo indirizzo.

Nel caso di applicazioni complesse su Raspberry Pi, torna utile verificare se l'NTP è sincronizzato con una sorgente e quindi si può fare affidamento sulla funzione microtime(true) per le temporizzazioni.

Nel caso in cui sia richiesta all'applicazione una risposta quasi-realtime (il kernel standard del Raspberry non consente l'utilizzo in hard-realtime), la chiamata periodica al comando ntpstat introduce una latenza che porterebbe all'esecuzione a singhiozzo del programma.

La soluzione adottata è quella di creare un file su filesystem tmpfs, che risiede in RAM, che viene aggiornato da un processo separato dal programma principale, il quale a sua volta verificherà il contenuto del file per sapere se l'NTP è sincronizzato oppure no. La lettura del file è molto più veloce e di durata prevedibile rispetto all'esecuzione di ntpstat, tanto da poter essere chiamata ad ogni ciclo del programma.

Per prima cosa bisogna creare un filesystem tmpfs. Creiamo il mountpoint:

$ sudo mkdir /mnt/pirun1/

Il filesystem dovrà essere montato prima dell'avvio dello script, è consigliabile aggiungere una riga a /etc/fstab:

tmpfs /mnt/pirun1 tmpfs size=256k

ntp dovrà essere installato e configurato, anche ntpstat dovrà essere installato.
Lo script creerà il file /mnt/pirun1/NtpSync, che conterrà "1" se NTP è in sync, "0" in caso contrario, può essere lanciato in background o con screen (i.e. in /etc/rc.local) e dovrà restare sempre in esecuzione.

<?php

error_reporting
(E_ALL);

# Apro in scrittura il file su tmpfs
# se non esiste lo crea
$fhandle fopen("/mnt/pirun1/NtpSync""c");

# La scrittura dello stato avviene solo in caso di acquisizione
# o perdita del sync, per risparmiare risorse
# Lo stato del ciclo precedente viene salvato nella variabile:
$LastValue 2;
# Inizializzo a 2 in modo che poi, confrontata con 1 o 0 sia sempre falsa e
# faccia scrivere sempre il file temporaneo all'avvio dello script;

while (true) {
  
system("ntpstat > /dev/null 2> /dev/null"$return_var);
  
/*
   * Non mi interessa l'output di ntpstat, la solo la variabile di ritorno:
   * è =0 se è in sync, !=0 se è fuori sync
   *
   * Oltre a definire una variabile per identificare lo stato synced/unsynced,
   * imposto l'intervallo di controllo: se sono in sync, posso accettare
   * un ritardo nella segnalazione (l'orario non sarà immediatamente sbagliato),
   * ma quando vado in sync lo devo sapere in tempi brevi.
   */
  
if ($return_var === 0) {
    
$IsSynced 1;
    
$PollingInterval 1000000;
  } else {
    
$IsSynced 0;
    
$PollingInterval 20000;
  }

  
# Se cambia lo stato, il file viene aggiornato.
  
if ($IsSynced <> $LastValue) {
    
fseek($fhandle0);
    if (
$IsSynced === 1) {
      
fwrite($fhandle"1");
      
LogRow("In sync" PHP_EOL);
    } else {
      
fwrite($fhandle"0");
      
LogRow("Out of sync" PHP_EOL);
    }
  }
  
$LastValue $IsSynced;
  
usleep($PollingInterval);
}

function 
LogRow($text) {
  echo (
date("c") . " " $_SERVER["SCRIPT_NAME"] . " - " $text);
}

lunedì 1 maggio 2017

I principi base del miglioramento

Decalogo operativo per puntare al miglioramento:
  1. Sbarazzarsi di tutti i preconcetti e le attuali opinioni su come devono essere fatte le cose.
  2. Pensare a come funzionerà il nuovo metodo, non come a non funzionerà.
  3. Non accettare scuse. Rinnegare completamente lo status quo.
  4. Non cercare la perfezione. Un miglioramento completato inizialmente al 50% può essere considerato soddisfacente se quest'ultimo si è dimostrato centrato rispetto agli obiettivi che ci si era preposti.
  5. Correggere gli errori nel momento in cui sono scoperti.
  6. Non spendere troppi soldi in miglioramenti.
  7. I problemi vanno visti come opportunità per utilizzare la propria intelligenza.
  8. Chiedersi "Perché?" almeno 5 volte, fino a che non si individua la causa ultima del problema.
  9. Le idee di 10 persone sono migliori di quelle di una sola.
  10. Il miglioramento non conosce limiti.

giovedì 27 marzo 2014

Scaricare i referti con Linux dall'Usl 1 Umbria

Questa è quello che succede se cercate di scaricare i referti dal sito dell'USL1 dell'Umbria con Firefox su Ubuntu Linux. La versione di Firefox è la 27.0.1, che ha integrato un lettore PDF.
Inoltre sul mio PC sono installati anche Evince e Okular.


Anche se campeggia in evidenti caratteri rossi l'allarme che non avete installato un lettore PDF per visualizzare ed eventualmente stampare i documenti, compilate i campi e cliccate su Estrai Referti.


Il referto verrà visualizzato e sarà possibile scaricarlo senza problemi.

venerdì 7 febbraio 2014

Emergency stop

Se immagini come questa vi fanno drizzare i peli sulla schiena, probabilmente vi occupate di sicurezza di macchine. Chi invece ha coperto il fungo di emergenza di questa porta automatica non ha la vostra stessa sensibilità.


In parziale difesa dell'autore di questa geniale soluzione, devo dire che probabilmente la porta in movimento non rappresenta un grave rischio per l'incolumità delle persone, tenendo conto che un arresto involontario può invece intrappolare una persona all'interno.
Ma non ho resistito a immortalare quest'opera d'arte :)

venerdì 31 gennaio 2014

Condivisioni con e senza autenticazione su Samba

Samba può essere configurato per creare delle condivisioni accessibili a tutti liberamente oppure previa autenticazione impostando in smb.conf la variabile security:

security = share # senza autenticazione
security = user # con autenticazione, default

In alcuni casi, però, e necessario gestire i permessi degli accessi e contemporaneamente avere delle shares disponibili senza autenticazione. Potrebbe anche essere la stessa directory, della quale cui uno o più utenti possono modificarne i contenuti, ma che deve essere accessibile in lettura a tutti gli altri.

In questo caso, è necessario settare le variabili:

[global]
  security = user
  map to guest = Bad User

La seconda riga dice a Samba di considerare gli utenti che forniscono un nome utente inesistente (Bad User) come guest.

Un esempio di share pubblica può essere la seguente:

[public]
  comment = Condivisione pubblica
  path = /var/public_share
  browseable = yes

  read only = yes
  guest ok = yes
  guest only = yes

domenica 29 settembre 2013

Ricordi di Springfield

Dialogo con mio figlio Lorenzo, 2 anni e 8 mesi:
  • Lorenzo: “oh Fla', mi plendi la macchinina pel favóle?”
  • Io: “Lorenzo, il papà non si chiama per nome, tu mi devi chiamare papà.”
  • Lorenzo: “Va beeene...”
  • ...
  • Lorenzo: “oh Fla', ho fatto il ponte con le costluzioni, ti piace?”
  • Io: “Sì Bart, è bellissimo...”