Operazioni programmate e periodiche

Loris Tissino

30 giugno 2009

Ora (e data) di sistema

L'ora e la data di sistema possono essere visualizzate con il comando date. In assenza di indicazioni, il formato di visualizzazione rispetta il locale corrente.

$ date
ven feb 22 09:37:09 CET 2008

$ LANG=POSIX date
Fri Feb 22 09:38:18 CET 2008

Rappresentazione delle date

È importante che nella rapppresentazione di date e ore non vi siano ambiguità. Ciò è valido soprattutto nei casi in cui è prevista una qualche forma di elaborazione automatica.

I problemi più comuni riguardano:

Formati di rappresentazione

Il comando date permette di usare alcuni formati standard predefiniti o di crearne di personalizzati:

$ date --rfc-2822  # formato usato per l'email
Fri, 22 Feb 2008 09:57:02 +0100

$ date --utc  # riferimento al tempo coordinato universale
ven feb 22 09:42:32 UTC 2008

$ date +"Settimana n. %U dell'anno %Y" # formato personalizzato
Settimana n. 07 dell'anno 2008

$ date +%s  # numero di secondi dall'Epoch
1203677970

Nota: i secondi possono andare da 0 a 60 per tener conto del secondo intercalare (supportato solo in rappresentazione).

Fuso orario

Informazioni sui fusi orari "attivabili" si possono trovare nel file /usr/share/zoneinfo/zone.tab. Il file /etc/localtime è una copia del (o un link simbolico al) file corrispondente della directory /usr/share/zoneinfo.

Modifica dell'ora di sistema

L'ora di sistema può essere modificata con il comando sudo date --set.

L'ora dell'hardware clock

L'orologio hardware, in funzione a calcolatore spento, cede il passo all'orologio di sistema quando questo viene avviato.

Si può vedere o impostare l'ora dell'orologio hardware con il comando hwclock.

$ hwclock -r
ven 22 feb 2008 11:54:06 CET  -0.283391 seconds

$ sudo hwclock --systohc  # imposta l'ora dell'hc basandosi su quella di sistema
$ sudo hwclock --hctosys  # imposta l'ora di sistema basandosi su quella dell'hc

L'ora esatta

Può essere utile recuperare l'ora esatta da un server apposito, rintracciabile consultando la lista di server pubblici disponibili.

Per visualizzare l'ora può essere dato il comando rdate -p <servername>. Per impostarla si dovrà dare il comando sudo rdate <servername> (o l'analogo sudo ntpdate <servername>. Ovvie norme di buona condotta prevedono che si evitino richieste troppo frequenti.

Per sistemi comuni può essere utile impostare l'ora all'avvio (eventualmente gestendo ritardi sistematici con adjtimex).

Per sistemi server, che rimangono sempre accesi ed hanno necessità di precisione maggiore (e di modifiche meno drastiche all'ora di sistema), è consigliabile una gestione tramite un demone ntp, che tiene in considerazione il ritardo dell'orologio di sistema ed effettua aggiustamenti graduali.

Timestamp dei file

Ad ogni file sono associati tre timestamp riportanti data e ora di:

Ad esempio:

$ stat documento.txt 
  File: `documento.txt'
[...]
Access: 2008-02-22 14:41:18.000000000 +0100
Modify: 2008-02-22 14:41:01.000000000 +0100
Change: 2008-02-22 14:42:14.000000000 +0100

Modifica della data di cambiamento di un file

È possibile visualizzare la data di ultimo cambiamento di un file anche con il comando date -r:

$ date -r documento.txt 
ven feb 22 14:41:01 CET 2008

Con touch si possono modificare i timestamp di un file "copiandoli" da quelli di un altro file preso come riferimento.

$ touch -r documento.txt altrodocumento.txt 
$ stat altrodocumento.txt 
[...]
Access: 2008-02-22 15:30:59.000000000 +0100
Modify: 2008-02-22 14:41:01.000000000 +0100
Change: 2008-02-22 15:31:41.000000000 +0100

Creare un file impostandone la data

È possibile creare un file indicando la data di modifica (o di accesso/modifica). Ciò si può rivelare utile per effettuare delle ricerche (vedi find).

$ touch --date '12 February 2009 13:30' /tmp/12FEB
$ touch -t 200903211430 /tmp/21MAR
$ ls -l /tmp/12FEB /tmp/21MAR 
-rw-r--r-- 1 loris docenti 0 2009-02-12 13:30 /tmp/12FEB
-rw-r--r-- 1 loris docenti 0 2009-03-21 14:30 /tmp/21MAR

Epoch

I sistemi Unix memorizzano le date come numero di secondi passati dall'inizio dell'anno 1970 (epoch). Attualmente vengono supportate date comprese nell'intervallo dal 13 dicembre 1901 al 19 gennaio 2038 (il numero di secondi è memorizzato in un campo di 32 bit con segno).

$ touch -t 190112132145.52 /tmp/BEGIN   # data valida: 13 dicembre 1901, ore 21:45:52
$ touch -t 190112132145.51 /tmp/BEGIN   # data non valida: ... ore 21:45:51
touch: invalid date format `190112132145.51'

$ touch -t 203801190414.07 /tmp/END        # data valida: 19 gennaio 2038, ore 04:14:07
$ touch -t 203801190414.08 /tmp/END        # data non valida: ... ore 04:14:08
touch: invalid date format `203801190414.08'

Uptime

Con il comando uptime si può sapere da quanto tempo il sistema è in uso, nonché il carico di lavoro nell'ultimo minuto, negli ultimi cinque minuti, nell'ultimo quarto d'ora.

$ uptime
 17:02:36 up  3:08,  3 users,  load average: 1.19, 1.09, 1.14

Calendario

Se si desidera ottenere un calendario si può usare il programma cal o ncal:

$ cal
   febbraio 2008    
do lu ma me gi ve sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

$ ncal
    febbraio 2008
lu     4 11 18 25   
ma     5 12 19 26   
me     6 13 20 27   
gi     7 14 21 28   
ve  1  8 15 22 29   
sa  2  9 16 23      
do  3 10 17 24      

Raffinatezze di ncal

Il programma ncal permette di:

Esempi:

$ seq 2008 2010 | xargs -i ncal -e {}
23 marzo 2008
12 aprile 2009
 4 aprile 2010

$ ncal 10 1582   # in Italia il passaggio al calendario gregoriano è avvenuto nel 1582
    ottobre 1582
lu  1 18 25         
ma  2 19 26         
me  3 20 27         
gi  4 21 28         
ve 15 22 29         
sa 16 23 30         
do 17 24 31    

Misurazione del tempo di esecuzione

Con il comando time si può misurare il tempo impiegato per l'esecuzione di un programma.

$ time echo "scale=2000; 4*a(1)" | bc -l
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
[...]
real    0m5.579s
user    0m5.520s
sys     0m0.012s

Attenzione: la Bash ha un proprio comando time implementato internamente: se si vuole usare il programma esterno time, lo si deve richiamare esplicitamente con /usr/bin/time.

Esecuzione programmata

Se si vuole eseguire un comando ad una certa ora, si può usare il comando at.

$ at 17:30
warning: commands will be executed using /bin/sh
at> echo questo è un test
at> echo dovrebbe essere eseguito alle 17.30
at> <EOT>
job 2 at Fri Feb 22 17:30:00 2008

L'output del comando viene inviato via posta elettronica.

$ mail
"/var/mail/loris": 1 message 1 new
>N   1 Loris Tissino      ven feb 22 17:30  13/435   Output from your job     
& 1
Subject: Output from your job        2
To: loris@localhost
Date: Fri, 22 Feb 2008 17:30:00 +0100 (CET)
From: loris@localhost (Loris Tissino)

questo è un test
dovrebbe essere eseguito alle 17.30
& q
Held 1 message in /var/mail/loris

Esecuzione programmata (2)

Il comando at dispone di alcune abbreviazioni. Ad esempio:

$ at noon 26.02.08
$ at teatime tomorrow
$ at now + 2 minutes

Nota: visto che at legge i comandi da eseguire dallo standard input, si possono sfruttare i meccanismi di ridirezione.

$ at midnight < listacomandi
$ echo cp -v file1 file2 | at 12:30

Esecuzione programmata (3)

Il comando atq permette di vedere quali sono i lavori programmati:

$ atq
6       Fri Feb 22 17:43:00 2008 a loris
5       Sat Feb 23 16:00:00 2008 a loris
4       Tue Feb 26 12:00:00 2008 a loris

Per la cronaca, i lavori da eseguire vengono salvati come script sh nella directory /var/spool/cron/atjobs.

Con il comando atrm si può rimuovere un lavoro dalla coda.

I file /etc/at.allow e /etc/at.deny permettono di indicare, rispettivamente, quali siano gli utenti a cui è permesso o non permesso accodare lavori con at.

Esecuzione batch

Il comando batch permette di impostare l'esecuzione di un programma attendendo il momento opportuno (quando cioè il carico di lavoro del calcolatore scende sotto un certo livello).

$ batch 
warning: commands will be executed using /bin/sh
at> ./bigcompile
at> <EOT>
job 12 at Sat Feb 23 11:44:00 2008

Sleep

Il programma sleep consente di sospendere l'esecuzione di uno script per un determinato numero di secondi, minuti, ore o giorni.

$ date +%H:%M:%S.%N; sleep 2s; date +%H:%M:%S.%N
11:26:14.948671731
11:26:16.954542400

Lettura di variabile dalla shell con timeout

In uno script bash, può essere comodo porre un timeout quando viene chiesto in input un valore:

$ read -p 'Inserisci nome (hai cinque secondi per farlo): ' -t 5 NOME 
Inserisci nome (hai cinque secondi per farlo): john

Esecuzione periodica: watch

Se si vuole eseguire un certo comando ogni x secondi, watch è il programma da usare.

$ watch ls -l /tmp

$ watch --differences ls -l /tmp
       # evidenzia le differenze dall'ultimo output
$ watch --differences=cumulative ls -l /tmp 
       # evidenzia le diff. dall'inizio
$ watch -n 20 ls -l /tmp
       # esegue ls -l ogni 20 secondi

Esecuzione periodica: cron

Se si vuole eseguire un certo comando ogni giorno ad una certa ora, oppure ogni x ore, e cose del genere, ci si deve affidare al demone crond.

Per modificare i propri comandi programmati, l'utente deve usare il comando interattivo crontab

$ crontab -e               # per modificare la propria programmazione
$ sudo crontab -e john     # per modificare la programmazione dell'utente john
$ crontab -l               # per visualizzare la propria programmazione
$ sudo crontab -u john -l  # per visualizzare la programmazione dell'utente john

Configurazione di cron

Ogni riga del file di conigurazione della programmazione di cron è composta da cinque campi:

Ulteriori informazioni si possono trovare in crontab(5).

E se il calcolatore è spento?

... viene in soccorso anacron.