Nella scorsa lezione abbiamo introdotto l'interprete dei comandi, ovvero
la shell, presentandone alcune funzioni di base.
Sebbene rappresenti un'interfaccia piuttosto ostica per coloro
che sono abituati a lavorare in ambienti grafici, tuttavia essa
costituisce la soluzione più idonea ed efficace per chi debba
lavorare a stretto contatto con il sistema operativo (tipicamente
i programmatori), offrendo nondimeno funzionalità interessanti
anche per gli utenti comuni.
Abbiamo accennato al comportamento predefinito di molti programmi
Unix riguardo la lettura dallo standard input e la scrittura sullo
standard output.
Naturalmente, un ambiente di lavoro che si voglia definire personalizzabile
(o customizzabile secondo l'attuale terminologia), deve
permettere di modificare questo comportamento e, difatti, Unix
ha introdotto il concetto di redirezione dello standard
input e dello standard output, consistente nella possibilità di
indirizzare il flusso dei caratteri in ingresso e/o in uscita
da/verso un altro file.
Questa utile funzionalità offerta dalla shell utilizza il carattere
'<' (minore) per redirigere lo standard input e il carattere
'>' (maggiore) per redirigere lo standard output.
Ad es. il comando:
$ sort < sorgente.txt
prende il suo input dal file 'sorgente.txt' e stampa l'output
sullo schermo (lo scopo del programma sort è quello di
ordinare alfabeticamente le linee di testo ricevute in input).
Analogamente:
$ sort < sorgente.txt > destinazione.txt
prende il suo input dal file 'sorgente.txt' e scrive l'output
sul file 'destinazione.txt'; se quest'ultimo file non esiste viene
creato, altrimenti viene sovrascritto.
Molte nuove shell consentono anche di redirigere lo standard
output in aggiunta (utilizzando i caratteri '>>') e di redirigere
lo standard error (con i caratteri '2>').
Ad es.:
$ sort >> destinazione.txt 2> errori.txt
scrive i messaggi di errore nel file 'errori.txt' e l'output viene
accodato al contenuto del file 'destinazione.txt', ovvero se il
file esiste non viene sovrascritto, ma gli vengono aggiunti i
nuovi dati.
Spesso può presentarsi l'esigenza di utilizzare i dati di output
di un programma come input per un altro programma.
Una prima soluzione potrebbe essere quella di utilizzare la redirezione
verso/da un file temporaneo da rimuovere successivamente.
Ad es. nella riga:
$ sort < sorgente.txt > temp.txt; head -20 temp.txt; rm
-f temp.txt
si è utilizzata la concatenazione di comandi, indicata
con il metacarattere ';', per eseguire in successione tre comandi:
1) prendere le righe contenute nel file 'sorgente.txt', ordinarle
alfabeticamente e scriverle sul file 'temp.txt';
2) prendere le prime 20 righe del file 'temp.txt' e stamparle
sullo standard output;
3) rimuovere il file 'temp.txt' (l'opzione -f forza la
cancellazione senza chiedere conferma all'utente).
Notiamo che, in questo esempio, l'esecuzione dei comandi successivi
è subordinata al successo dell'esecuzione dell'istruzione precedente.
Infatti se programma sort non va a buon fine il file 'temp.txt'
sarà vuoto (o non esisterà affatto), per cui non avrà senso eseguire
i programmi seguenti.
Per consentire un controllo più completo sui programmi concatenati,
molte shell offrono un operatore di controllo, indicato con '&&',
che si comporta come un operatore booleano AND: se il valore di
uscita di ciò che sta a sinistra è vero, viene eseguito anche
quanto sta a destra.
Quindi scrivendo:
$ sort < sorgente.txt > temp.txt && head -20 temp.txt
&& rm -f temp.txt
il programma head sarà eseguito se sort terminerà
con successo e rm se head sarà terminato con successo.
Per comprendere questo funzionamento, occorre sapere che ogni
programma termina con un valore di uscita che viene passato al
programma “padre” che lo ha invocato (tipicamente
la shell, ma può essere anche un qualsiasi altro programma utente).
In caso di successo, il programma termina passando al “padre”
il valore 0, altrimenti un valore diverso da 0 può essere utilizzato
dal “padre” per capire la ragione dell'errata terminazione
del programma.
Nel nostro esempio head sarà eseguito se e solo se sort
terminerà con il valore 0 e rm sarà eseguito se e solo
se head sarà terminato con valore 0.
Torna all'indice Generale del corso di Corso di Sistemi Operativi di Software Planet