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);
}

Nessun commento:

Posta un commento

I comenti sono moderati, non compariranno subito ma dopo l'approvazione. Grazie per la pazienza.