Se il kernel è il nucleo del sistema, la shell è il guscio, ovvero il meccanismo di accesso al sistema per chi sta all’esterno. Per shell si intende l’interfaccia (a caratteri) tramite la quale l’utente può operare sul sistema. La shell è un programma che gestisce la comunicazione fra l’utente ed il sistema operativo, interpretando ed eseguendo i comandi dell’utente (la shell viene chiamata anche interprete dei comandi o command interpreter). Dunque, in sostanza la shell è un programma che attende i comandi digitati dall’utente e li interpreta secondo la propria sintassi (mette in atto un meccanismo di parsing dei comandi). Tale programma occupa tutto lo schermo suddividendolo generalmente in 25 righe per 80 colonne (su ogni riga possono essere visualizzati un massimo di 80 caratteri). Un esempio di shell è riportato nella fig. 3.1
Per far capire all’utente che si attende l’inserimento di un comando, la shell presenta un
prompt (invito) che tipicamente è costituito dal carattere dollaro ‘$’ per gli utenti che
non hanno diritti amministrativi sul sistema e dal carattere cancelletto ‘#’ per il
superuser. Man mano che i comandi vengono impartiti ed eseguiti, la shell ripropone il
prompt sulla riga seguente, rimanendo in attesa di un altro comando. Quando le righe
dello schermo sono già state tutte “utilizzate” (man mano che vengono digitati i
comandi, questi vengono lasciati scritti sullo schermo, come anche l’output dei vari
programmi) lo schermo viene virtualmente spostato verso il basso effettuando uno
scroll, ovvero tutte le righe vengono spostate di una posizione vero l’alto in modo da
liberare l’ultima riga (chiaramente si perde la visualizzazione della prima riga, la
meno recente tra quelle visualizzate sullo schermo). In realtà tale meccanismo non
elimina fisicamente la prima riga, ma esiste uno scrollback buffer (o buffer di shell),
ovvero una parte della memoria in cui viene tenuta traccia delle ultime righe di testo
visualizzate sullo schermo. In genere il numero di righe di cui il sistema tiene traccia è
superiore a quello che è visualizzato dallo schermo (generalmente il sistema tiene traccia
dell’ultimo centinaio di righe di testo visualizzate). Per poter visualizzare le righe
ormai “scrollate”, ovvero uscite dallo schermo, ma ancora mantenute nello scrollback
buffer, è sufficiente utilizzare le combinazioni di tasti
e
che permettono la visualizzazione a pagine delle righe contenute nello scrollback
buffer.
Di seguito al prompt è visualizzato un carattere underscore ‘__’ (oppure ‘__’) che lampeggia: il cursore1. Esso indica sempre la posizione dello schermo in cui apparirà il prossimo carattere visualizzato (sia esso inserito da tastiera, che facente parte dell’output di un programma). Infatti, man mano che i caratteri vengono visualizzati sullo schermo, il cursore si sposta verso destra (ovviamente quando questo arriva al margine destro del monitor, viene riposizionato al margine sinistro della riga successiva).
Ogni shell ha anche un proprio linguaggio di programmazione (scripting language) più o meno evoluto che permette di scrivere semplici programmi (script) interpretabili dalla stessa shell, molto utili per automatizzare alcune operazioni sui file.
La shell in genere è anche dotata di uno storico dei comandi (command history), ovvero permette di richiamare velocemente i comandi più recenti digitati dall’utente.
È compito della shell gestire quello che si definisce ambiente o environment, ovvero un insieme di impostazioni generali che un programma utilizza per eseguire i propri compiti. L’ambiente è definito per mezzo di variabili, dette appunto variabili d’ambiente (environment variable) che la shell deve essere in grado di creare, leggere e modificare.
La shell inoltre si deve preoccupare anche della suddivisione in token degli argomenti passati ad un comando, ovvero deve effetuare quella che viene detta tokenizzazione (suddivisione) degli argomenti. Può capitare infatti che un’applicazione possa richiedere dei parametri sulla riga di comando. L’applicazione, una volta lanciata, si troverà ad avere a che fare con gli argomenti passati sulla riga di comando: l’applicazione non dovrà gestire la suddivisione degli argomenti passati in token poiché questa operazione è svolta automaticamente dalla shell2.
La struttura dei comandi impartiti dalla shell è la seguente:
$ command [argument [...]]
dove
[username@hostname working_directory]$
dove
È da notare il fatto che il simbolo utilizzato come carattere finale del prompt è convenzionalmente ‘$’ per gli utenti comuni e ‘#’ per il superuser;
La variabile di ambiente3 nella quale è memorizzata la stringa utilizzata come prompt è PS1;
Nei sistemi Unix-like è una convenzione diffusa utilizzare come argomenti che specificano delle opzioni di funzionamento di un comando, dei caratteri preceduti dal simbolo ‘-’ (es. -a, -x, ...). Tali argomenti sono detti appunto opzioni e si è soliti riferirsi alla relativa notazione con il termine short form (forma breve). Le opzioni secondo la notazione short form possono essere indicate anche specificando l’elenco dei caratteri che le identificano di seguito al simbolo ‘-’ (es. l’insieme delle opzioni -a e -b può essere specificato anche come -ab). Esiste anche un’altra forma convenzionale, di più recente introduzione, per l’espressione delle opzioni che consiste in stringhe precedute dalla sequenza di caratteri “--” (es. --name). Tale notazione è detta long form (forma estesa). Le opzioni specificate con la long form non possono essere raggruppate come invece può essere fatto con la short form.
Ad esempio, il comando
$ date -u
in cui è specificata l’opzione -u (short form) è identico al comando
$ date --utc
in cui l’opzione --utc è specificata secondo la sintassi più recente (long form). Il
comando
$ date -R -u
indica l’utilizzo delle opzioni -R e -u. Questo può essere ottenuto anche specificando
l’elenco delle lettere che indicano le opzioni, cioè “Ru”, di seguito al simbolo ‘-’,
ovvero
$ date -Ru
È opportuno tenere presente che il carattere spazio ‘ ’ (o blank) assume un significato
particolare per la shell, infatti esso è interpretato come carattere di separazione tra i
comandi e gli argomenti e tra l’elenco degli argomenti stessi da passare come input ai
comandi.
Anche se l’interfaccia della shell dei sistemi Unix-like può sembrare piuttosto scarna, essa costituisce comunque un potente strumento attraverso il quale un utente può gestire tutte le funzionalità del sistema.