[precedente] ISDN - Copertina - Emacs e archivi [successivo]

Articoli


Data e ora con Linux

Per Linux (ma in realtà per qualsiasi server Unix) l'ora corrente è molto importante, e lo dimostra la quantità di orologi presenti nel sistema stesso (oltre all'orologio standard, nel kernel c'è anche un'orologio per il realtime, e altri orologi), come l'ora corrente sia usata spesso e come il sistema diventi ``isterico'' negli attimi successivi un cambio di orario (generalmente per correggere il minuto di anticipo che può avere l'orologio interno).

Ogni computer ha un orologio hardware, alimentato a batteria, e che permette di tenere l'ora esatta nel tempo anche quando la macchina è spenta. Ma il kernel ha anch'esso un suo orologio, che si allinea con quello hardware all'avvio del sistema, ma poi prosegue indipendente (infatti se si cambia l'ora da Linux ma non la si scrive nell'HW, al successivo riavvio il kernel si riallinea all'orologio HW).

Di qui l'esigenza che l'orologio HW abbia un'orario valido. C'è una differenza sostanziale, però: l'orologio HW è un semplice contatore stupido di secondi, dietro al kernel Linux (e Unix in genere) ci sono anche librerie intelligenti, come quelle che gestiscono i fusi orari e i cambi di orario estate/inverno.

Una cosa da tenere sempre presente è che il kernel usa l'ora internazionale, ovvero quella relativa al meridiano di Greenwich. L'orologio HW può essere sincronizzato con l'ora locale oppure anch'esso con l'ora internazionale. Se la macchina viene avviata anche con sistemi operativi diversi da Linux, probabilmente l'orologio HW è sincronizzato con l'ora locale, altrimenti ci sono molti più vantaggi ad usare l'ora internazionale anche per l'orologio HW.

Questo perché lavorando il kernel con l'ora internazionale, ogni richiesta di lettura dell'ora locale viene filtrata tramite la libreria principale (libc5, e, man mano che si diffonderà, anche la libc6) ed elaborata calcolando il fuso orario e la presenza dell'ora legale. Se anche l'orologio HW è sincronizzato con l'ora internazionale non serve neanche cambiare l'ora in concomitanza con il cambio dell'ora legale.

date: mostra l'ora, ma non solo

Il comando date mostra l'ora corrente per il fuso orario locale. Ogni utente può specificare il proprio fuso orario tramite la variabile d'ambiente TZ, così chi lavora su un server molto remoto e da un fuso orario diverso, può lavorare utilizzando l'ora locale del posto da cui è collegato.

Ma date va più in là. È possibile adattare il formato d'uscita alle proprie preferenze, decidendo quali informazioni stampare e in che ordine. Dando come parametro un ``+qualcosa'' viene usato quel formato, e potrebbe essere utile per script automatici di archiviazione, quando serve creare dei file contenenti una parte della data (spesso si tratta di mese e anno). Ad esempio il comando:

tar cvfz etc-`date +%y%m`.tgz /etc

crea un archivio tgz con il contenuto di /etc, chiamato con un nome contenente quattro cifre che rappresentano l'anno e il mese in cui viene fatta l'archiviazione dei dati.

Ma non solo!

Generalmente questi backup si fanno alla fine di un giorno o di un mese, quindi si rischia di archiviare con il numero del mese in corso il materiale risalente il mese prima.

Ma date non finisce di stupire. Se il 1o giorno del mese deve essere fatto il backup di una directory con i dati elaborati il mese prima, basta sostituire il comando precedente con:

tar cvfz etc-`date -d "a month ago" +%y%m`.tgz /etc

Qui si prende come data di riferimento il mese precedente, e si compone il nome del file prendendo le ultime due cifre dell'anno e le due cifre del mese, ma riferendosi sempre al mese precedente quello attuale. Così è anche possibile sapere il giorno della settimana di una data qualsiasi, tipo Natale:

date --date '25 Dec' +%A

A seconda che il database ``locale'' sia completo o meno, il giorno della settimana apparirà stampato integralmente in inglese o in italiano.

Impostare data e ora

Se la data non è corretta, è necessario sistemarla. Questo compito è riservato all'utente root, visto che un cambio di data è critico per il sistema. Ad esempio potrebbe capitare che alcuni file vengano spostati nel futuro, e che ci sia una sovrapposizione di tempi che rende un po' illeggibile alcuni log. Pure make si arrabbia se trova dei file con la data nel futuro!

Conviene per praticità impostare la data da Linux rispetto che dal bios, in quanto da Linux avviene il calcolo automatico del fuso orario, comodo se l'orologio HW usa l'ora internazionale. Se si dà a date un parametro puramente numerico (senza quindi precederlo da altre opzioni), questo viene interpretato come l'ora da impostare nel sistema. I campi in questione sono:

Il comando clock

Qui entra in gioco il comando /sbin/clock.

Attenzione: c'è un altro comando con lo stesso nome nel sistema, che crea un orologio analogico o digitale su un display grafico (X). L'amministratore dovrebbe in caso di dubbi chiamare /sbin/clock per esteso.

Questo comando permette di leggere l'orologio HW, allineare l'orologio del kernel all'orologio HW, o impostare l'ora del kernel nell'orologio HW. Rispettivamente le opzioni da dare sono: -r, -s e -w. L'opzione -u dice di trattare l'ora dell'orologio HW come se fosse l'ora internazionale. Generalmente dovrebbe esserci una chiamata a /sbin/clock nei file di inizializzazione del sistema, per la distribuzione Debian questo file è /etc/init.d/boot (per le altre distribuzioni provate a lanciare un grep nei file di /etc/rc.d/ o simili).

Il comando rdate

Nulla di meglio è allineare automaticamente l'orologio del proprio computer all'ora di un server affidabile. A questo scopo viene in aiuto il comando rdate.

rdate chiede l'ora ad un server specificato nella riga di comando e aggiorna l'orologio del kernel. Ci sono delle opzioni che permettono di non mostrare l'ora o di leggerla dal serve remoto senza impostare l'orologio locale.

Una cosa furba sarebbe mettere in /etc/ppp/ip-up queste righe (così si allinea l'orologio del proprio PC ogni volta che parte la connessione ad Internet):

/usr/sbin/rdate -s time.ien.it
/sbin/clock -wu

La prima chiede l'ora esatta all'Istituto Elettrotecnico Nazionale, che mantiene l'ora di riferimento per l'Italia, la seconda riga allinea l'orologio HW a quest'orario, in modo da essere perfetti anche se spegniamo e riaccendiamo il PC in seguito.

rdate potrebbe avere problemi se il sito risponde in ritardo, ma penso che se la risposta arriva entro pochi secondi, rimanga comunque entro limiti accettabili.

L'ora dei file

Ogni file su disco dispone di ben 3 (tre) orari: l'ora di creazione, l'ora dell'ultima modifica, e l'ora dell'ultimo accesso. Generalmente ls mostra l'ora dell'ultima modifica, ma con alcune opzioni può mostrare qualsiasi orario.

Il comando touch permette di modificare la data di modifica dei file (se si hanno i permessi sufficienti). Questo può forzare la ricompilazione di programmi usando make, oppure allineare la data di modifica di un gruppo di file ad un'ora precisa.

In particolare ultimamente ho avuto bisogno di spostare di pochissimo l'ora di modifica di alcuni file, per evitare che wget li riscaricasse dai siti originali ritenendoli troppo vecchi. È bastato spostare di 2 ore in avanti l'ora di modifica per far credere a wget che non servisse riscaricare i file.

Ecco lo script che ho usato:

find . -type f -print | while read nomefile
do
  curdate=`ls -l --full-time $nomefile | cut -c 47-66`
  newdate=`date -d "$curdate + 2hour" +\%m\%d\%H\%M\%Y`
  touch $newdate $nomefile
done

La prima riga dice di prendere tutti i file che si trovano sotto la directory corrente e ogni sottodirectory. La terza riga preleva la data di modifica del file per esteso tramite ls. La quarta analizza la data, la fa avanzare di 2 ore e la converte in un formato compatibile per touch. La quinta riga sistema la nuova data del file.

Letture consigliate

Per maggiori informazioni si consiglia la lettura delle seguenti man page (molte sono già disponibili in italiano, altre lo saranno presto se qualcuno volesse contribuire al progetto ILDP di traduzione delle man page): date(1), ls(1), touch(1), clock(8), rdate(8).

di Michele Dalla Silvestra


[precedente] ISDN - Copertina - Emacs e archivi [successivo]