[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]


31. Pianificazione dei processi (scheduling)

La pianificazione dei processi, o scheduling, riguarda l'esecuzione in date e orari stabiliti e la modifica delle priorità. Il mezzo attraverso il quale si controlla l'avvio di un processo in un momento stabilito è dato dal sistema Cron, ovvero dal demone omonimo (`cron'), mentre la priorità può essere modificata attraverso il valore nice.

La tabella 31.1 elenca i programmi e i file a cui si accenna in questo capitolo.

Nome Descrizione
cron Programma demone per l'esecuzione dei comandi pianificati.
crontab Accesso e modifica del file della pianificazione dei comandi.
/etc/crontab File di pianificazione di sistema.
/var/spool/cron/crontabs Directory contenente i file di pianificazione degli utenti.
atrun Mette in esecuzione i job di `at' e `batch'.
at Accoda un job da eseguire in un momento successivo stabilito.
batch Accoda un job da eseguire quando il carico del sistema lo consente.
atq Interroga la coda dei job.
atrm Elimina i job dalla coda.
/etc/at.allow Determina quali utenti possono utilizzare `at' e `batch'.
/etc/at.deny Determina quali utenti non possono utilizzare `at' e `batch'.
nice Esegue un comando modificandone il valore nice.
renice Cambia il valore nice di processi in funzione.
nohup Esegue un comando rendendolo insensibile al segnale `SIGHUP'.

Tabella 31.1: Riepilogo dei programmi e dei file per la gestione dello scheduling.

31.1 Cron

Nel bel mezzo della notte, mentre si sta lavorando isolati da qualunque rete, potrebbe capitare di notare un'intensa attività del disco fisso senza giustificazione apparente. Di solito si tratta del demone `cron'.

Cron è il sistema che si occupa di eseguire, attraverso il demone `cron', dei comandi in momenti determinati in base a quanto stabilito all'interno della sua configurazione, rappresentata dai file crontab. Questi file possono essere diversi, solitamente uno per ogni utente che ha la necessità di pianificare l'esecuzione di alcuni comandi, e uno generale per tutto il sistema.

I file crontab vengono creati attraverso il programma `crontab' e questo permette di non dovere sapere necessariamente dove devono essere collocati e in che modo vanno nominati. Oltre che per un fatto di relativa comodità, l'esistenza del programma `crontab' permette di evitare che i file crontab siano accessibili a utenti che non ne siano i proprietari. Inoltre, non è necessario preoccuparsi di avvisare il demone `cron' dell'avvenuto cambiamento nella situazione dei piani di esecuzione. *1*

L'output dei comandi che il sistema Cron mette in esecuzione, se non è stato ridiretto in qualche modo, per esempio a `/dev/null' o a un file, viene inviato con un messaggio di posta elettronica all'utente cui appartiene il file crontab.

Il demone `cron' viene avviato di norma durante la procedura di inizializzazione del sistema. Di questo demone ne esistono almeno due tipi diversi per GNU/Linux: Vixie Cron e Dillon's Cron, dai nomi dei loro autori. Nelle sezioni seguenti si fa riferimento in particolare al sistema Cron di Paul Vixie.

Vedere cron(1), crontab(1) o crontab(8), e crontab(5).

31.1.1 # cron (Vixie)

cron

`cron' è un demone funzionante sullo sfondo (background) che si occupa di interpretare i file crontab collocati in `/var/spool/cron/crontabs/' oltre a uno speciale, `/etc/crontab', il cui formato è leggermente diverso.

Dal momento che la sostanza del funzionamento di questo programma sta nell'interpretazione dei file crontab, le altre notizie sul suo utilizzo sono riportate in occasione della presentazione di quei file.

31.1.2 $ crontab

crontab [<opzioni>]

`crontab' permette di creare o modificare il file crontab di un determinato utente. In particolare, solo l'utente `root' può agire sul file crontab di un altro utente. Di solito, `crontab' viene utilizzato con l'opzione `-e' per modificare o creare il file crontab.

I file crontab vengono poi utilizzati dal demone `cron' che si occupa di eseguire i comandi lì indicati.

Sintassi

crontab [-u <utente>] <file>

Sostituisce il file crontab con il contenuto del file indicato come argomento.

crontab -l [<utente>]

Visualizza il file crontab dell'utente.

crontab -e [<utente>]

Crea o modifica il file crontab dell'utente.

crontab -r [<utente>]

Cancella il file crontab dell'utente.

Utilizzo

crontab -e

Inizia la modifica del file crontab dell'utente.

crontab -l

Visualizza il contenuto del file crontab dell'utente. Il suo contenuto potrebbe apparire come nel listato seguente:

# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.1466 installed on Thu Aug 21 17:39:46 1997)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
10 6 * * * echo "ciao ciao"

---------

crontab -r

Elimina il file crontab dell'utente.

31.1.3 /var/spool/cron/crontabs/*

I file contenuti nella directory `/var/spool/cron/crontabs/' sono i file crontab degli utenti comuni, creati generalmente attraverso il programma `crontab'. Ogni utente ha il proprio, con il nome dell'utente stesso, e i comandi contenuti al suo interno vengono eseguiti con i privilegi dell'utente proprietario del file crontab.

Le righe vuote sono ignorate e così anche quelle dove il primo carattere diverso da uno spazio lineare (sia spazi veri e propri che caratteri di tabulazione) è il simbolo `#', che serve così a introdurre dei commenti. Un record significativo può essere un assegnamento di una variabile di ambiente o un comando Cron.

L'assegnamento di una variabile può avvenire nel modo consueto,

<nome> = <valore>

dove gli spazi attorno al segno di uguaglianza sono facoltativi e il valore assegnato può essere indicato eventualmente con virgolette (singole o doppie). *2*

Il demone `cron' utilizza una serie di variabili di ambiente per determinare il proprio comportamento. Alcune di queste ricevono un valore predefinito dal demone `cron' stesso, e tutte, tranne `LOGNAME', possono essere modificate attraverso un assegnamento all'interno del file crontab.

Un file crontab tipico può contenere solo comandi di Cron. Il formato di questo può essere riassunto brevemente nel modo seguente:

<data-orario> <comando>

Il comando viene eseguito attraverso la shell indicata all'interno della variabile `SHELL', mentre l'indicazione data-orario si scompone in altri cinque campi.

<minuti> <ore> <giorni-del-mese> <mesi> <giorni-della-settimana>

I campi possono contenere un asterisco (`*') e in tal caso rappresentano ogni valore possibile di quel campo. Per esempio, `* * * * *' rappresenta ogni minuto di ogni ora di ogni giorno del mese di ogni mese di ogni giorno della settimana.

A parte il caso degli asterischi, all'interno di questi campi si possono indicare dei valori numerici secondo gli intervalli seguenti:

Per ognuno di questi campi, i valori possono essere indicati in vari modi con diversi significati.

Quello che appare dopo i cinque campi dell'orario viene interpretato come un comando da eseguire. Più precisamente, viene considerato tale tutto quello che appare prima della conclusione della riga o di un segno di percentuale (`%'). Quello che eventualmente segue dopo il primo segno di percentuale viene interpretato come testo da inviare allo standard input del comando stesso. Se all'interno del testo da inviare appaiono altri segni di percentuale, questi vengono trasformati in codici di interruzione di riga.

Segue un esempio commentato di file crontab tratto da crontab(5).

# Utilizza «/bin/sh» per eseguire i comandi, indipendentemente da
# quanto specificato all'interno di «/etc/passwd».
SHELL=/bin/sh

# Invia i messaggi di posta elettronica all'utente «tizio»,
# indipendentemente dal proprietario di questo file crontab.
MAILTO=tizio

# Esegue 5 minuti dopo la mezzanotte di ogni giorno.
5 0 * * *       $HOME/bin/giornaliero >> $HOME/tmp/out 2>&1

# Esegue alle ore 14:15 del primo giorno di ogni mese.
# L'output viene inviato tramite posta elettronica all'utente «tizio».
15 14 1 * *     $HOME/bin/mensile

# Esegue alle 22 di ogni giorno lavorativo (da lunedì al venerdì).
# In particolare viene inviato un messaggio di posta elettronica a «caio».
0 22 * * 1-5    mail -s "Sono le 22" caio%Caio,%%è ora di andare a letto!%

# Esegue 23 minuti dopo mezzanotte, dopo le due, dopo le quattro,...,
# ogni giorno.
23 0-23/2 * * * echo "Ciao ciao"

# Esegue alle ore 04:05 di ogni domenica.
5 4 * * 0       echo "Buona domenica"

31.1.4 /etc/crontab

Il file `/etc/crontab' ha un formato leggermente diverso da quello dei file crontab normali. In pratica, dopo l'indicazione dei cinque campi data-orario, si inserisce il nome dell'utente in nome del quale deve essere eseguito il comando indicato successivamente.

Nell'esempio seguente, tutti i comandi vengono eseguiti per conto dell'utente `root', ovvero, vengono eseguiti con i privilegi di questo utente.

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# Run any at jobs every minute
* * * * * root [ -x /usr/sbin/atrun ] && /usr/sbin/atrun

# run-parts
01 * * * * root run-parts /etc/cron.hourly
02 1 * * * root run-parts /etc/cron.daily
02 2 * * 0 root run-parts /etc/cron.weekly
02 3 1 * * root run-parts /etc/cron.monthly

# Remove /tmp, /var/tmp files not accessed in 10 days (240 hours)
41 02 * * * root /usr/sbin/tmpwatch 240 /tmp /var/tmp

# Remove formatted man pages not accessed in 10 days
39 02 * * * root /usr/sbin/tmpwatch 240 /var/catman/cat?

Una parte dell'esempio mostrato è abbastanza comune nelle varie distribuzioni GNU/Linux e merita una spiegazione aggiuntiva. A metà dell'esempio appare l'avvio del comando `run-parts' a cadenza oraria, giornaliera, settimanale e mensile. Per esempio, la direttiva

01 * * * * root run-parts /etc/cron.hourly

avvia il comando `run-parts /etc/cron.hourly' ogni ora. `run-parts' è un programma (a volte realizzato in forma di script) che avvia tutti gli eseguibili contenuti nella directory indicata come argomento; per cui, `run-parts /etc/cron.hourly' serve ad avviare tutto quello che c'è nella directory `/etc/cron.hourly/'.

Nella propria distribuzione GNU/Linux, il nome utilizzato per questo programma potrebbe essere diverso, e così anche i nomi delle directory, ma quello che conta è comprendere che per inserire un'elaborazione nei momenti più comuni, basta mettere il programma o lo script relativo nella directory che rappresenta la cadenza desiderata. Questo, tra le altre cose, permette di realizzare dei pacchetti applicativi con tutto ciò che serve per fare in modo che il sistema Cron si preoccupi di loro nel modo corretto (senza dover intervenire manualmente nei file crontab).

Una realizzazione molto semplice di `run-parts' in forma di script potrebbe essere simile a quella seguente:

#!/bin/sh

for I in $1/* ; do
    if [ -x $I ]; then
	$I
    fi
done

exit 0

31.1.5 /etc/cron.d/*

Alcune distribuzioni GNU/Linux introducono una variante al Cron di Paul Vixie, estendendo il crontab di sistema ai file contenuti nella directory `/etc/cron.d/'. Questi file, sono altrettanti crontab, che hanno la stessa sintassi di `/etc/crontab', e vengono scanditi assieme a quello principale. L'utilità di questo sta nel fatto di evitare che i pacchetti che si installano debbano modificare il file crontab di sistema, limitandosi a gestire il proprio file particolare nella directory `/etc/cron.d/'.

31.2 Anacron

Cron è un sistema di pianificazione adatto principalmente per gli elaboratori che restano in funzione ininterrottamente per molto tempo; infatti, se non si accende mai l'elaboratore nell'intervallo di tempo in cui sarebbe previsto l'avvio di elaborazioni a cadenza giornaliera, settimanale o mensile, queste verrebbero automaticamente escluse. Per risolvere il problema, e cioè per garantire l'avvio di quelle elaborazioni, si può utilizzare Anacron.

Anacron è un sistema di pianificazione molto semplice, che permette soltanto di programmare l'esecuzione di elaborazioni determinate a cadenza giornaliera, o a multipli di giorni. La sua logica è molto semplice: utilizza un file di configurazione, `/etc/anacrontab', concettualmente analogo al crontab di Cron, in cui si indica semplicemente l'intervallo in giorni per l'esecuzione di processi determinati. Per mantenere memoria di ciò che è stato fatto, utilizza dei file nella directory `/var/spool/anacron/' per annotarsi in che giorno ha eseguito un certo job per l'ultima volta.

Questo sistema è gestito in pratica dall'eseguibile `anacron', che si comporta normalmente come un demone, che resta in funzione solo per il tempo necessario a completare il suo lavoro: il giorno successivo, dovrà essere riavviato.

31.2.1 /etc/anacrontab

Il file `/etc/anacrontab' si utilizza per configurare il comportamento di Anacron. Il file può contenere la definizione di alcune variabili di ambiente, così come si farebbe con una shell Bourne, e quindi è composto da una serie di record (righe), che descrivono i vari job da gestire. Come nel caso dei file crontab normali, le righe bianche e quelle vuote vengono ignorate, e così sono ignorate le righe che iniziano con il simbolo `#'.

<n-giorni> <n-minuti-ritardo> <nome-attribuito-al-job> <comando>

I record che definiscono i job di Anacron sono composti da campi separati da spazi bianchi di qualunque tipo:

  1. il primo campo è un numero che esprime la cadenza in giorni con cui deve essere eseguito il comando;

  2. il secondo campo è un altro numero che esprime un ritardo in secondi, che deve essere atteso prima di cominciare;

  3. il terzo campo attribuisce un nome al job;

  4. l'ultimo campo è il comando corrispondente al job, e in questo caso particolare, il campo finale può contenere spazi.

Il significato dei campi dovrebbe essere abbastanza logico. In particolare, il ritardo viene stabilito per evitare che in un certo momento possano essere messi in funzione simultaneamente troppi processi, tenendo conto che è normale inserire l'avvio di Anacron all'interno della stessa procedura di inizializzazione del sistema.

È necessario attribuire un nome a ogni record (il job, secondo questa logica), per permettere a Anacron di annotarsi quando il comando relativo viene eseguito, in modo da determinare ogni volta se il tempo previsto è scaduto o meno.

La definizione di variabili di ambiente può essere necessaria, specialmente quando si prevede l'avvio di Anacron in modo automatico, attraverso la procedura di inizializzazione del sistema, e in tal caso diventa fondamentale attribuire un valore alle variabili `SHELL' e `PATH'. Si osservi l'esempio seguente:

# /etc/anacrontab

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

1	5	cron.daily	run-parts /etc/cron.daily
7	10	cron.weekly	run-parts /etc/cron.weekly
30	15	cron.monthly	run-parts /etc/cron.monthly

Oltre alla definizioni delle variabili, si può vedere la dichiarazione di tre job che riguardano l'esecuzione di altrettanti comandi a cadenza giornaliera, settimanale e mensile. I tre job vengono avviati a distanza di cinque minuti uno dall'altro, e anche il primo di questi attende cinque minuti per sicurezza. Si intuisce che questa pianificazione si affianchi a quella del crontab di sistema, in modo da garantire l'esecuzione degli script contenuti nelle directory `/etc/cron.daily', `/etc/cron.weekly' e `/etc/cron.monthly'.

31.2.2 $ anacron

anacron [<opzioni>]

L'eseguibile `anacron' è quello che svolge in pratica il lavoro di gestione del sistema Anacron. Può essere avviato anche da utenti comuni, ma in generale questo non si fa, e si lascia che sia la stessa procedura di inizializzazione del sistema a preoccuparsene.

Quando viene avviato, si mette normalmente a funzionare sullo sfondo, disimpegnandosi dal processo che lo ha avviato (diventando figlio del processo principale); quindi legge il file di configurazione e controlla nella directory `/var/spool/anacron/' quando è stata l'ultima volta che ha eseguito ogni job previsto; di conseguenza avvia i comandi relativi ai job scaduti, aggiornando i file relativi nella stessa directory. L'avvio di questi comandi avviene di norma rispettando il ritardo indicato nel file di configurazione. Al termine, l'eseguibile `anacron' termina di funzionare.

Di solito, Anacron viene gestito direttamente dalla procedura di inizializzazione del sistema, e in tal caso, è normale che l'eseguibile sia avviato con l'opzione `-s', che fa in modo di mettere in serie l'esecuzione dei job. In pratica, si evita che venga avviato un altro job prima che sia terminata l'esecuzione di quello precedente.

Per evitare conflitti tra Anacron e Cron, nel momento in cui potrebbe essere consentito a Cron di eseguire le stesse elaborazioni, conviene fare in modo che Cron «avvisi» Anacron nel momento in cui queste vengono svolte. In pratica, si utilizza l'opzione `-u' di `anacron', con la quale si ottiene proprio questo: aggiornare le date annotate nei file contenuti nella directory `/var/spool/anacron/'. Per comprendere meglio la cosa, si pensi alla situazione tipica, ovvero quella in cui si predispongono le solite directory `/etc/cron.daily/', `/etc/cron.weekly/', e `/etc/cron.monthly/', che devono contenere gli script da eseguire con cadenza giornaliera, settimanale e mensile, da parte di Cron o Anacron, indifferentemente. Per evitare che Anacron rifaccia quello che potrebbe avere già fatto Cron, si mette lo script `0anacron' in ognuna di queste directory (lo zero iniziale garantisce che questo sia il primo script a essere avviato). Nel caso si `/etc/cron.daily/0anacron', il contenuto potrebbe essere:

#!/bin/bash

anacron -u cron.daily

Questo dice a Anacron di aggiornare la data abbinata al job `cron.daily', in modo da evitare di ripeterne l'esecuzione prima del necessario; inoltre, questo script non crea problemi a Anacron stesso, nel momento in cui dovesse essere avviato come parte del comando relativo a un job.

31.3 At

L'esecuzione di un'elaborazione può essere necessaria una volta sola in una data e in un orario stabilito, oppure quando l'attività del sistema è ridotta. Anche se in generale la gestione della pianificazione dei processi è gestita dal sistema Cron, per questo scopo particolare gli si affianca il sistema At.

A seconda dei casi, può trattarsi di un sottosistema di pianificazione dipendente da Cron, oppure può essere gestito da un demone indipendente: nel primo caso viene gestito dal programma `atrun', che a sua volta viene avviato periodicamente (di solito una volta al minuto) da Cron; nel secondo caso si fa affidamento sul demone `atd' che non interferisce in alcun modo con Cron.

Per verificare in che modo è organizzata la propria distribuzione GNU/Linux a proposito di At, si può osservare il file crontab di sistema, oppure quello dell'utente root; in alternativa si può osservare l'albero dei processi (con `pstree') per vedere se c'è in funzione il demone `atd'. Naturalmente, nel caso di gestione attraverso il demone `atd', dovrebbe esserci anche uno script che si occupa di avviarlo e di fermarlo nell'ambito della procedura di inizializzazione del sistema (`/etc/init.d/atd' o simile).

`atrun' o `atd' eseguono dei job accodati su diversi tipi di code dai programmi `at' e `batch'. Queste code sono classificate per importanza (priorità) attraverso una lettera alfabetica: le lettere minuscole si riferiscono a job accodati da `at', mentre quelle maiuscole rappresentano job accodati da `batch'.

La differenza tra questi due comandi sta nel fatto che il primo accoda job da eseguire in un momento determinato, mentre con il secondo, questi vengono eseguiti non appena l'attività del sistema raggiunge un livello sufficientemente basso da non disturbare l'esecuzione di processi più importanti.

Le code di questi job si trovano normalmente all'interno di `/var/spool/cron/atjobs/'.

L'utilizzo di `at' e `batch' può essere controllato attraverso due file: `/etc/at.allow' e `/etc/at.deny'. Se esiste `/etc/at.allow', solo gli utenti elencati al suo interno possono utilizzare `at' e `batch'. Se `/etc/at.allow' non esiste, viene preso in considerazione `/etc/at.deny' e gli utenti elencati al suo interno non possono utilizzare `at' e `batch'. Se questi due file non esistono, allora non si pongono limiti all'utilizzo di questi programmi.

31.3.1 Ambiente

Nel momento in cui si decide di fare eseguire un comando in un momento successivo a quello attuale, si presenta il problema di definire l'ambiente in cui questo dovrà trovarsi. In linea di massima si può dire che si fa riferimento alla stessa situazione in cui ci si trova nel momento in cui si accoda il job. Si tratta dell'identità dell'utente (il numero UID), della directory corrente, della maschera dei permessi (per la creazione dei file) e delle variabili di ambiente. In particolare, le variabili `TERM' e `DISPLAY', e il parametro `$_' non mantengono il loro valore originale.

31.3.2 Restituzione dell'output

Quando si pianifica l'esecuzione di un comando in un momento successivo, si ha il problema di stabilire dove debba essere diretto il suo output. Sarebbe buona norma indicarlo già nel comando, per esempio ridirigendo sia lo standard output che lo standard error in un file. Se qualcosa sfugge, l'output non ridiretto viene inviato all'utente che ha accodato il job attraverso un messaggio di posta elettronica (più precisamente attraverso `/bin/mail').

31.3.3 $ at

at [<opzioni>] <orario>

Il programma `at' permette di pianificare, in un certo orario, l'esecuzione di un determinato comando attraverso la shell predefinita, corrispondente a `/bin/sh'. Il comando o i comandi da eseguire vengono ricevuti dallo standard input, oppure da un file se ciò è specificato attraverso le opzioni.

L'orario di esecuzione può essere specificato in vari modi, anche combinando alcune parole chiave che in generale si riferiscono ai termini e alle abitudini dei paesi di lingua inglese.

Orari

Segue un elenco di ciò che può essere utilizzato ragionevolmente in ambito internazionale.

---------

<hhmm> [AM|PM] | <hh>:<mm> [AM|PM]

Specifica un orario espresso in ore e minuti. Il simbolo `:' di separazione tra le due cifre che rappresentano le ore e quelle dei minuti, è facoltativo. L'utilizzo delle sigle `AM' e `PM' non è consigliabile: in generale, è preferibile esprimere gli orari utilizzando la notazione internazionale di 24 ore.

A un orario si possono aggiungere due indicazioni ulteriori: `today' (oggi); `tomorrow' (domani).

<mmggaa> | <mm>/<gg>/<aa> | <gg>.<mm>.<aa>

Una data può essere espressa con un gruppo di sei cifre, separate eventualmente da una barra obliqua (`/'), e in tal caso si deve usare la sequenza mese-giorno-anno, oppure utilizzando il punto (`.') come separatore, e allora si può utilizzare la sequenza giorno-mese-anno.

now

La sigla `now' viene usata per definire il momento attuale, e si usa in combinazione con una definizione di ritardo.

<momento-di-partenza> + <quantità-del-ritardo> <unità-di-tempo>

Questa forma permette di stabilire un ritardo nell'avvio dei processi a partire dal momento indicato come riferimento. Il momento iniziale può essere `now' che si riferisce al momento presente, oppure un orario preciso. La durata del ritardo viene espressa da un numero che rappresenta una quantità definita subito dopo: `minutes' (minuti); `hours' (ore); `days' (giorni); `weeks' (settimane).

Alcune opzioni

-q <coda>

Permette di definire la coda. Si tratta di una lettera alfabetica minuscola, dalla `a' alla `z' e dalla `A' alla `Z'. La coda predefinita di `at' è quella corrispondente alla lettera `a', mentre quella di `batch' è quella della lettera `b'. Se si utilizzano lettere successive, i compiti associati riceveranno un valore nice maggiore.

-m

Attraverso il sistema di posta elettronica, invia un messaggio all'utente che ha accodato la richiesta quando il compito è stato svolto.

-f <file>

Legge i comandi da eseguire da un file, invece che dallo standard input.

-l

Si comporta come `atq' e informa dei job in coda.

-d

Si comporta come `atrm'.

-v

Riguarda il funzionamento in modalità `atq' e permette di conoscere l'orario di esecuzione.

-c <job>...

Emette attraverso lo standard output il contenuto della coda associata al numero, o ai numeri di job indicati. Viene in pratica emesso il contenuto del file che costituisce la coda associata al job indicato.

Esempi

at -f routine 13:30 + 3 days

Esegue i comandi contenuti nel file `routine', fra tre giorni, alle ore 13:30.

at 15:00 tomorrow

Eseguirà domani alle ore 15:00 i comandi che verranno inseriti di seguito (si conclude con una combinazione [Ctrl+d]).

at 10:00 10.11.99

Il 10 novembre 1999 alle ore 10:00 eseguirà i comandi da specificare successivamente.

31.3.4 $ batch

batch [<opzioni>] [<orario>]

`batch' è normalmente un collegamento all'eseguibile `at'. Quando `at' viene avviato usando il nome `batch', i compiti associati vengono eseguiti non appena il livello di carico del sistema diventa ragionevolmente basso da permetterlo. In pratica, si può anche indicare un momento particolare (un orario), ma l'esecuzione avverrà solo quando il sistema avrà un'attività ridotta.

31.3.5 $ atq

atq [<opzioni>]

`atq' è normalmente un collegamento al programma `at'. Quando `at' viene avviato usando il nome `atq', emette l'elenco dei job in coda. Se viene specificata una coda attraverso l'opzione `-q', si limita a fare l'analisi di quella in particolare.

31.3.6 $ atrm

atrm <job>...

`atrm' è normalmente un collegamento al programma `at'. Quando `at' viene avviato usando il nome `atrm', elimina dalla coda i job specificati nella riga di comando.

31.3.7 Analisi di un esempio

L'esempio seguente dovrebbe permettere di comprendere il meccanismo attraverso cui viene registrata la situazione dell'istante in cui si accoda un job. L'intenzione è quella di fare eseguire il programma `ls', alle ore 16:30, nella directory corrente nel momento in cui si accoda il job, generando il file `esempio' (nella stessa directory) con l'output ottenuto. L'utente che accoda il comando è `tizio'.

at 16:30[Invio]

warning: commands will be executed using /bin/sh

at> ls > ./esempio[Invio]

at> [Ctrl+d]

Job 1 at 1999-09-22 16:30

A questo punto si può dare un'occhiata alla coda.

atq[Invio]

1	1999-09-22 16:30 a tizio

Con i privilegi dell'utente `root', è possibile dare un'occhiata all'interno della directory `/var/spool/cron/atjobs/' per scoprire che è stato creato uno script, in questo caso denomianto `a0000400ee8c66'. Segue il listato del suo contenuto.

#!/bin/sh
# atrun uid=1001 gid=1001
# mail  tizio 0
umask 2
HZ=100; export HZ
HOSTNAME=tizio; export HOSTNAME
PS1=\\u@\\h:\\w\\\$\ ; export PS1
USER=tizio; export USER
MACHTYPE=i486-pc-linux-gnu; export MACHTYPE
MAIL=/var/spool/mail/tizio; export MAIL
LANG=it_IT.ISO-8859-1; export LANG
LOGNAME=tizio; export LOGNAME
SHLVL=1; export SHLVL
HUSHLOGIN=FALSE; export HUSHLOGIN
HOSTTYPE=i486; export HOSTTYPE
OSTYPE=linux-gnu; export OSTYPE
HOME=/home/tizio; export HOME
PATH=:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11; export PATH
LESSCHARSET=latin1; export LESSCHARSET
cd /home/tizio || {
	 echo 'Execution directory inaccessible' >&2
	 exit 1
}
ls > ./esempio

Nella prima parte viene definita la maschera dei permessi attraverso il comando `umask'.

umask 2

Quindi seguono una serie di assegnamenti di variabili esportate che riproducono l'ambiente del momento in cui il job è stato sottoposto.

HZ=100; export HZ
HOSTNAME=tizio; export HOSTNAME
PS1=\\u@\\h:\\w\\\$\ ; export PS1
USER=tizio; export USER
...

Al termine, prima dell'esecuzione dei comandi richiesti, viene eseguito lo spostamento nella directory che, nel momento in cui si sottoponeva il job, era quella corrente. Se l'operazione fallisce viene interrotto lo script.

cd /home/tizio || {
	 echo 'Execution directory inaccessible' >&2
	 exit 1
}

31.4 Priorità

La priorità di esecuzione di un processo può essere modificata attraverso il valore nice che viene sommato, in modo algebrico, al valore di questa.

Quando si parla di priorità occorre però fare attenzione al contesto: di solito, un valore basso significa precedenza (quindi priorità) rispetto ai valori superiori. Spesso però si parla di priorità maggiore o minore in maniera impropria: quando si consulta della documentazione in cui si fa riferimento al concetto di priorità bisogna fare bene attenzione a non confondersi.

Dal momento che il valore nice viene sommato alla priorità, se nice è pari a zero, non altera la priorità di esecuzione di un processo, se invece ha un valore positivo ne rallenta l'esecuzione, e ancora, un valore negativo ne accelera il funzionamento.

Alcuni programmi ricevono dal sistema un valore di priorità particolarmente basso per motivi fisiologici di funzionamento del sistema stesso. Il pretendere di portare agli stessi livelli di priorità altri programmi potrebbe comportare il blocco del sistema operativo. In pratica, anche se si tenta di dare a un processo un valore nice negativo, spesso il sistema non reagisce con un'eguale diminuzione del valore della priorità. Inoltre, solo l'utente `root' può attribuire ai processi valori nice inferiori a zero.

Di solito quindi, il valore nice viene usato per ridurre la velocità di esecuzione di un processo in modo da alleggerire l'impiego di risorse da parte dello stesso. Spesso si combina questa tecnica assieme all'utilizzo di elaborazioni sullo sfondo.

A fianco del problema della modifica della priorità di esecuzione di un programma c'è quello di mantenere in funzione un programma anche dopo la disconnessione del terminale dal quale questo viene avviato.

31.4.1 $ nice

nice [<opzioni>] [<comando> [<argomenti>]]

Esegue un comando con un valore nice diverso dal normale. Minore è questo valore, maggiori saranno le risorse (in termini di rapidità di esecuzione) che il sistema gli concede. L'esecuzione senza alcun argomento visualizza il livello attuale del valore nice. Se viene specificato il nome di un comando, ma non viene indicato il livello di variazione (adjustment), il valore nice del comando indicato come argomento, sarà incrementato di 10 rispetto al valore attuale. Il livello di variazione può andare da un minimo di -20 a un massimo di +19, ma solo l'utente `root' può attribuire variazioni negative.

Alcune opzioni

-n <variazione>

Definisce esplicitamente il livello di variazione del valore nice da attribuire al comando da eseguire.

31.4.2 $ renice

renice <priorità> [[-p] <pid>...] [[-g] <pid-di-gruppo>...] [[-u] <utente>...]

`renice' modifica il valore nice di uno o più processi. È possibile indicare un processo singolo, un processo che faccia capo a un gruppo (un processo dal quale discendono altri processi), oppure tutti i processi che appartengono a un certo utente.

Opzioni

-p <pid>

Indica esplicitamente che si fa riferimento a un processo singolo, indicato attraverso il numero PID.

-g <pid-di-gruppo>

Indica un processo, attraverso il numero PID, e si riferisce anche a tutti i suoi processi discendenti.

-u <utente>

Indica che si fa riferimento a tutti i processi avviati con i privilegi dell'utente indicato per nome.

31.4.3 $ nohup

nohup <comando> [<argomenti>]

Esegue un comando facendo in modo che questo non sia interessato dai segnali di interruzione di linea (`SIGHUP'). In questo senso, `nohup' permette di avviare dei processi che non devono interrompersi nel momento in cui l'utente che li avvia termina la sua sessione di lavoro (chiude la connessione con il terminale). Naturalmente, questo ha senso se i programmi vengono avviati sullo sfondo.

In base a questo principio, cioè quello per cui si usa `nohup' per avviare un programma sullo sfondo in modo che continui a funzionare anche quando l'utente si scollega, la priorità di esecuzione viene modificata, aumentando il valore nice di cinque unità.

Il comando indicato come argomento non viene messo automaticamente sullo sfondo, per ottenere questo occorre aggiungere il simbolo `&' (e-commerciale) alla fine della riga di comando. Quando il comando indicato come argomento utilizza il terminale per emettere l'output, sia lo standard output che lo standard error vengono ridiretti verso il file `./nohup.out', oppure, se i permessi non lo consentono, verso il file `~/nohup.out'. Se questo file esiste già i dati vengono aggiunti.

Esempi

Segue un esempio che mostra in che modo si comporta `nohup'. Si comincia dall'avvio di una nuova copia della shell Bash nel modo seguente:

bash[Invio]

Viene avviato sullo sfondo il programma `yes' e il suo output viene semplicemente ridiretto verso `/dev/null':

nohup yes > /dev/null &[Invio]

[1] 1304

Il processo corrispondente ha il numero PID 1304. Si controlla lo stato dei processi attraverso `ps':

ps[Invio]

  PID TTY STAT  TIME COMMAND
...
 1304   1 R N  1:55 yes
...

Dalla colonna `STAT' si può osservare che `yes' ha un valore nice positivo (si osserva per questo la lettera `N'). Si controlla lo stato dei processi attraverso `pstree':

pstree -p[Invio]

init(1)-+-...
        |
        ...
        |-login(370)---bash(387)---bash(1303)-+-pstree(1341)
        |                                     `-yes(1304)
        ...

Si può osservare che `yes' è un processo figlio della shell Bash (l'eseguibile `bash') avviata poco prima. Si conclude l'attività della shell provocando un segnale di interruzione di linea per i processi che dipendono da questa:

exit[Invio]

Si controlla nuovamente lo stato dei processi attraverso `pstree':

pstree -p[Invio]

init(1)-+-...
        |
        ...
        |-login(370)---bash(387)---pstree(1359)
        ...
        |-yes(1304)
        ...

Adesso, `yes' risulta essere un processo figlio del processo principale (Init, ovvero l'eseguibile `init').

Probabilmente, facendo qualche esperimento, si può osservare che i processi sullo sfondo non terminano la loro esecuzione quando si conclude la sessione di lavoro della shell che li ha avviati, senza bisogno di utilizzare `nohup'. Tuttavia ci sono situazioni in cui `nohup' è indispensabile. Per esempio, se si sta lavorando con l'ambiente grafico X e si chiude una finestra di terminale, un eventuale programma sullo sfondo viene eliminato sicuramente, a meno di usare `nohup'.

---------------------------

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 Daniele Giacomini --  daniele @ pluto.linux.it


1.) Indipendentemente dal fatto che il demone `cron' necessiti o meno di essere avvisato.

2.) La possibilità di inserire degli assegnamenti di variabili di ambiente all'interno di un file crontab è una particolarità del sistema Cron di Paul Vixie.

3.) Normalmente, `/bin/sh' è un collegamento alla shell predefinita, ovvero a Bash (`/bin/bash'), che se avviata così, si comporta in modo compatibile con la shell Bourne.


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]