Shell La shell, che sta tra l'utente e il sistema operativo, opera come un interprete di comandi. Legge l'input dal terminale e traduce i comandi in azioni, azioni che vengono intraprese dal sistema. La shell è simile al command.com in DOS. Una volta effettuato il login nel sistema, viene assegnata la shell di default. La shell, al suo avvio, legge i suoi file di inizializzazione e può settare alcune variabili di ambiente, i path di ricerca dei comandi, gli alias dei comandi ed eseguire qualche comando specificato in questi file. La prima shell è stata la shell Bourne, &man.sh.1;. Ogni piattaforma Unix dispone della shell Bourne o di una shell Bourne compatibile. Questa shell ha molte buone caratteristiche per controllare l'input e l'output, ma non è molto adatta all'utente interattivo. Per andare incontro a quest'ultimo è stata scritta la shell C, &man.csh.1;, presente ora in molti, ma non tutti, i sistemi Unix. Questa shell usa una sorta di sintassi C, il linguaggio con cui Unix è stato scritto, ma ha molte scomode implementazioni dell'input/output. La shell C ha il controllo dei job, quindi può mandare un job eseguito in background (sotto shell) in foreground (in shell corrente). Inoltre ha la funzione di history (storia dei comandi) che permette di modificare e ripetere comandi eseguiti precedentemente. Il prompt di default per la shell Bourne è $ (o &prompt.root; per l'utente root). Il prompt di default per la shell C è &prompt.user;. Sono disponibili in rete molte altre shell. Quasi tutte sono basate sulla shell &man.sh.1; o &man.csh.1; con estensioni per fornire il controllo dei job alla shell &man.sh.1;, permettere di manipolare il modo di esecuzione dei comandi su linea di comando, cercare attraverso i comandi eseguiti precedentemente, fornire il completamento dei nomi dei comandi, prompt personalizzati, ecc. Alcune delle seguenti shell maggiormente conosciute potrebbero essere sul proprio amato sistema Unix: la shell korn, ksh, di David Korn e la shell Bourne Again, &man.bash.1;, dal progetto GNU Free Software Foundations, entrambe basate su &man.sh.1;, la shell T-C, &man.tcsh.1; e l'estensione della shell C, cshe, entrambe bastate su &man.csh.1;. In seguito si descriveranno alcune delle caratteristiche di &man.sh.1; e &man.csh.1;, così per iniziare. Comandi built-in La shell ha alcuni comandi built-in, chiamati anche comandi nativi. Questi comandi sono eseguiti direttamente dalla shell e non chiamano nessun altro programma per essere eseguiti. Questi comandi built-in possono essere diversi tra le varie shell. Sh Per la shell Bourne alcuni dei comandi built-in più comunemente usati sono: : comando null . prende (legge ed esegue) i comandi da un file case condizionale case cd cambia la directory di lavoro ($HOME di default) echo scrive una stringa su standard output eval valuta l'argomento specificato e ritorna il risultato alla shell exec esegue il comando specificato rimpiazzando la shell corrente exit esce dalla shell corrente export condivide le variabili di ambiente specificate con le successive shell for condizionale di ciclo for if condizionale if pwd mostra la directory di lavoro corrente read legge una linea di input da standard input set setta le variabili di shell test valuta un'espressione come vera o falsa trap intrappola un tipo di segnale ed esegue comandi umask setta la maschera di default relativa ai permessi da impostare per i nuovi file unset resetta le variabili di shell wait attente che un specifico processo termini while condizionale di ciclo while Csh Per la shell C i comandi built-in maggiormente usati sono: alias assegna un nome a una funzione bg mette un job in background cd cambia la directory di lavoro corrente echo scrive una stringa su standard output eval valuta gli argomenti specificati e ritorna il risultato alla shell exec esegue il comando specificato rimpiazzando la shell corrente exit esce dalla shell corrente fg porta un job in foreground foreach condizionale di ciclo for glob crea un'espansione dei nomi di file su una lista senza tenere conto del carattere di escape \ history stampa la storia dei comandi della shell if condizionale if jobs mostra o controlla i job attivi kill termina un processo specifico limit setta dei limiti sulle risorse di sistema logout termina la shell di login nice comando abbassa la priorità di schedulazione del comando specificato nohup comando non termina il comando specificato quando la shell esce popd estrae un record dallo stack delle directory e ritorna nella directory estratta pushd cambia nella nuova directory specificata e aggiunge quella corrente nello stack delle directory rehash ricrea la tabella hash dei percorsi (path) per i file eseguibili repeat ripete un comando il numero di volte specificato set setta una variabile di shell setenv setta una variabile di ambiente per la shell corrente e per quelle successive source prende (legge ed esegue) comandi da un file stop ferma uno specifico job in background switch condizionale switch umask setta la maschera di default relativa ai permessi da impostare per i nuovi file unalias rimuove il nome alias specificato unset resetta le variabile di shell unsetenv resetta le variabili di ambiente wait attente la terminazione di tutti i processi in background while condizionale di ciclo while Variabili di ambiente Le variabili di ambiente sono usate per fornire informazioni ai programmi che si utilizzano. Si possono avere sia variabili globali di ambiente sia variabili locali di shell. Le variabili globali di ambiente sono inizializzate attraverso la propria shell di login e i nuovi programmi e le nuove shell ereditano l'ambiente della shell genitore. Le variabili locali di shell sono usate solamente dalla shell corrente e non sono passate ad altri processi. Un processo figlio non può passare una variabile al suo processo padre. Le variabili di ambiente correnti sono visualizzabili con i comandi &man.env.1; o &man.printenv.1;. Alcune comuni variabili sono: DISPLAY Il display grafico da usare, esempio nyssa:0.0 EDITOR Il path (percorso) del proprio editor di default, esempio /usr/bin/vi GROUP Il proprio gruppo di login, esempio staff HOME Il path della propria home directory, esempio /home/frank HOST Il nome host del proprio sistema, esempio nyssa IFS I separatori di campo interni, generalmente alcuni spazi bianchi (tab, spazio e new-line di default) LOGNAME Il nome del proprio login, esempio frank PATH I path per ricercare i comandi, esempio /usr/bin:/usr/ucb:/usr/local/bin PS1 La stringa del prompt primario, solamente shell Bourne ($ di default) PS2 La stringa del prompt secondario, solamente shell Bourne (> di default) SHELL La propria shell di login, esempio /usr/bin/csh TERM Il proprio tipo di terminale, esempio xterm USER Il proprio username, esempio frank Molte variabili di ambiente sono inizializzate automaticamente quando si effettua il login. Queste possono essere modificate e si possono definire altre variabili nei propri file di inizializzazione o in qualunque momento all'interno della shell. Alcune variabili che è possibile si voglia cambiare sono PATH e DISPLAY. La variabile PATH specifica le directory nelle quali saranno automaticamente cercati i comandi richiesti. Alcuni esempi sono nello script di inizializzazione di shell mostrato più avanti. Per la shell C si può settare una variabile globale di ambiente con un comando simile a quello usato per visualizzare le variabili: &prompt.user; setenv NOME valore e per la shell Bourne: $ NOME=valore; export NOME Si possono elencare le proprie variabili globali di ambiente con i comandi &man.env.1; o &man.printenv.1;. Si possono resettare queste variabili con i comandi unsetenv (shell C) o unset (shell Bourne). Per settare una variabile locale di shell in shell C si usa il comando set con la sintassi seguente. Senza opzioni set mostra tutte le variabili locali. &prompt.user; set nome=valore Per la shell Bourne si setta una variabile locale di shell con: $ nome=valore Il valore corrente di una variabile è accessibile attraverso le notazioni $nome o ${nome}. La shell Bourne, sh La shell &man.sh.1; usa il file di inizializzazione .profile posto nella home directory dell'utente. Inoltre può esserci un file di inizializzazione globale del sistema, esempio /etc/profile. In tal caso, il file globale del sistema sarà eseguito prima di quello locale. Un semplice file .profile potrebbe essere come il seguente: PATH=/usr/bin:/usr/ucb:/usr/local/bin:. # setta il PATH export PATH # rende disponibile PATH per le sotto-shell # setta il prompt PS1="{`hostname` `whoami`} " # setta il prompt, $ di default # funzioni ls() { /bin/ls -sbF "$@";} ll() { ls -al "$@";} # setta il tipo di terminale stty erase ^H # setta Control-H come tasto di cancellazione eval `tset -Q -s -m ':?xterm'` # richiede il tipo di terminale, presupponendo # xterm # umask 077 Ogni volta che si incontra il simbolo #, il resto di quella linea viene trattato come un commento. Nella variabile PATH ogni directory è separata da due punti (:) e il punto (.) specifica che la directory corrente è nel proprio path. Se il punto non è nel proprio path, lo stesso diventa un semplice elemento per eseguire un programma nella directory corrente: ./programma Non è una buona idea avere il punto (.) nel proprio PATH, in modo tale da non eseguire inavvertitamente un programma senza averne l'intenzione quando si usa il comando cd per spostarsi in differenti directory. Una variabile settata in .profile rimane valida solo nel contesto della shell di login, a meno che la si esporti con export o si esegua .profile in un'altra shell. Nell'esempio precedente PATH viene esportato per le sotto-shell. Si può eseguire un file con il comando built-int . di &man.sh.1;, esempio: . ./.profile Si possono creare proprie funzioni. Nell'esempio precedente la funzione ll, risultato di ls -al, lavora su un specifico file o directory. Con &man.stty.1; il carattere di cancellazione viene settato a Control H , che è usualmente il tasto di Backspace. Il comando &man.tset.1; richiede il tipo di terminale e assume questo a xterm se si conferma con invio <CR>. Questo comando è eseguito con un comando built-in di shell, eval, che prende il risultato del comando &man.tset.1; e lo usa come argomento per la shell. In questo caso l'opzione di &man.tset.1; setta le variabili TERM e TERMCAP e le esporta. L'ultima linea nell'esempio richiama il comando umask, facendo in modo che i file e le directory create non abbiano i permessi di lettura-scrittura-esecuzione per l'utenza gruppo e altri. Per altre informazioni su &man.sh.1;, digitare man sh al prompt di shell. La shell C, csh La shell C, &man.csh.1;, usa i file di inizializzazione .cshrc e .login. Alcune versioni usano un file di inizializzazione globale del sistema, ad esempio /etc/csh.login. Il proprio file .login è eseguito solamente quando si effettua il login. Il proprio file .cshrc è eseguito ogni volta in cui si avvia una shell &man.csh.1;, incluso quando si effettua il login. Questo file ha molte caratteristiche simili al file .profile, ma un differente modo di composizione. Qui si usano i comandi set o setenv per inizializzare una variabile, dove set viene usato per definire una variabile solo per la shell corrente, mentre setenv definisce una variabile per la shell corrente e per le altre sotto-shell. Le variabili di ambiente USER, TERM e PATH sono automaticamente importate ed esportate dalle variabili user, term e path della shell &man.csh.1;. Quindi setenv non è necessario per queste variabili. La shell C usa il simbolo ~ per indicare la directory home dell'utente in un path, come in ~/.cshrc o per specificare una directory di login di un altro utente, come in ~username/.cshrc. Alcune variabili predefinite usate dalla shell C sono: argv La lista degli argomenti della shell corrente cwd La directory di lavoro corrente history Imposta la dimensione della lista di history (storia) da memorizzare home La directory home dell'utente, visualizzabile con $HOME ignoreeof Quando viene settata, EOF ( Ctrl D ) viene ignorato dal terminale noclobber Quando viene settata si impedisce di redirigere l'output per sovrascrivere file esistenti noglob Quando viene settata si impedisce l'espansione dei nomi di file all'interno di un confronto con uno schema wild card path I path di ricerca dei comandi, visualizzabile con $PATH prompt Setta il prompt della linea di comando (&prompt.user; di default) savehist Numero di volte (di login) che bisogna mantenere memorizzata la lista di history nel file .history shell Il path name completo della shell corrente, visualizzabile con $SHELL status Il codice di stato di uscita dell'ultimo comando (0=uscita normale, 1=comando fallito) term Il proprio tipo di terminale, visualizzabile con $TERM user Il proprio nome utente, username, visualizzabile con $USER Un semplice file .cshrc potrebbe essere come il seguente: set path=(/usr/bin /usr/ucb /usr/local/bin ~/bin . ) # setta il path set prompt = "{`hostname` `whoami` !} " # setta il promt primario ; # % di default set noclobber # non redirige l'output su file esistenti set ignoreeof #ignora EOF (Ctrl+D) in questa shell set history=100 savehist=50 # mantiene una lista history di comandi e la # memorizza tra vari (50) login # alias alias h history # alias h per history alias ls "/usr/bin/ls -sbF" # alias ls per ls -sbF alias ll ls -al # alias ll per ls -sbFal (combina queste # opzioni con quelle di ls sopra citate) alias cd 'cd \!*;pwd' # alias cd per stampare la directory di lavoro # corrente dopo aver cambiato directory umask 077 Alcune nuove caratteristiche che non sono state viste nel file .profile (shell &man.sh.1;) sono noclobber, ignoreeof e history. Noclobber indica che l'output non può essere rediretto su un file esistente, mentre ignoreeof specifica che EOF ( Ctrl D ) non causa l'uscita dalla shell di login o l'uscita dal sistema. Con la caratteristica di history si possono richiamare comandi eseguiti precedentemente e rieseguirli, eventualmente con dei cambiamenti. Un alias permette di usare uno specifico nome alias al posto del comando completo. Nell'esempio precedente, il risultato di digitare ls sarà quello di eseguire /usr/bin/ls -sbF. Si può verificare quale comando ls è nel proprio path con il comando &man.which.1;, ad esempio: &prompt.user; which ls ls: alias di /usr/bin/ls -sbF Un semplice file .login potrebbe essere come il seguente: # .login stty erase ^H # setta Control+H come tasto di eliminazione set noglob # impedisce un confronto con uno schema wild card eval `tset -Q -s -m ':?xterm'` # chiede il tipo di terminale presupponendo # xterm unset noglob # riabilita un confronto con uno schema wild card Abilitando e disabilitando noglob intorno a &man.tset.1; si impedisce di confondere il tipo di terminale con qualche espansione dei nomi di file in un confronto con uno schema (pattern) wild card. Se si effettuano cambiamenti al proprio file di inizializzazione, questi possono essere attivati eseguendo il file modificato. Per la shell &man.csh.1; questo è possibile attraverso il comando built-in source, esempio: source .cshrc Per altre informazioni circa la shell &man.csh.1; digitare man csh al prompt di shell. Controllo dei job Con la shell C, &man.csh.1; e molte altre nuove shell, incluse alcune nuove shell Bourne, si possono mettere i job in background apporrendo & al comando, così come succede per la shell &man.sh.1;. Questo può anche essere fatto, una volta sottoposto il comando, digitando Control Z per sospendere il job e quindi bg per metterlo in background. Per riportarlo in foreground si digita fg. Si possono avere molti job eseguiti in background. Quando questi sono in background, non sono connessi alla tastiera per l'input, ma possono tuttavia mostrare l'output nel terminale, sparpagliandolo con qualsiasi cosa ci sia digitata o mostrata attraverso il job corrente. Si può avere la necessità di redirigere I/O in o da un file per un job in background. La propria tastiera è solamente connessa al corrente job in foreground. Il comando built-in jobs permette di elencare i propri job in background. Si può usare il comando &man.kill.1; per terminare un job in background. In questi comandi, con la notazione %n ci si riferisce all'n-esimo job in background, rimpiazzando n con il numero di job proveniente dall'output di jobs. Quindi si termina il secondo job in background con kill %2 e si riprende il terzo job in foreground con fg %3. History La shell C, la shell Korn e molte altre shell avanzate, mantengono informazioni sui comandi che sono stati eseguiti in shell. La quantità di storia memorizzabile dipende dalla shell utilizzata. Qui si descriveranno le caratteristiche di history della shell C. Si possono usare le variabili history e savehist per settare rispettivamente quanti comandi della shell corrente memorizzare e per quanti login mantenerli. Si può inserire in .cshrc la seguente linea per memorizzare 100 comandi della shell corrente fino a 50 prossimi login. set history=100 savehist=50 La shell mantiene traccia della storia dei comandi tra un login e l'altro memorizzandola nel file ~/.history. Si può usare il comando built-in history per richiamare i comandi eseguiti precedentemente, ad esempio per stampare gli ultimi 10: &prompt.user; history 10 52 cd workshop 53 ls 54 cd Unix_intro 55 ls 56 pwd 57 date 58 w 59 alias 60 history 61 history 10 Si può ripetere l'ultimo comando digitando !!: &prompt.user; !! 53 ls 54 cd Unix_intro 55 ls 56 pwd 57 date 58 w 59 alias 60 history 61 history 10 62 history 10 Si può ripetere un comando numerato introducendo il numero con un !, esempio: &prompt.user; !57 date Tue Apr 9 09:55:31 EDT 1996 Si può ripetere un comando che inizia con qualche stringa, introducendo la parte iniziale univoca della stringa con un !, esempio: &prompt.user; !da date Tue Apr 9 09:55:31 EDT 1996 Quando la shell valuta la linea di comando verifica subito la sostituzione di history prima di interpretare qualche altra cosa. Per usare uno di questi caratteri speciali in un comando di shell è necessario usare un escape, o effettuare un quoting, apporrendo un \ prima del carattere, esempio \!. I caratteri di sostituzione di history sono sintetizzati nella tabella seguente: Comandi di sostituzione di history per la shell C Comando Funzione sostitutiva !! ripete l'ultimo comando !n ripete il comando numero n !-n ripete l'n-esimo comando partendo dall'ultimo !str ripete il comando che inizia con la stringa str !?str? ripete il comando con all'interno str !?str?% seleziona il primo argomento che ha str all'interno !: ripete l'ultimo comando, generalmente usato con una modifica !:n seleziona l'n-esimo argomento dell'ultimo comando (n=0 è il nome del comando) !:n-m seleziona gli argomenti tra l'n-esimo e l'm-esimo argomento dell'ultimo comando !^ seleziona il primo argomento dell'ultimo comando (come !:1) !$ seleziona l'ultimo argomento dell'ultimo comando !* seleziona tutti gli argomenti del precedente comando !:n* seleziona gli argomenti dall'n-esimo all'ultimo, incluso, del precedente comando !:n- seleziona gli argomenti dall'n-esimo all'ultimo, escluso, del precedente comando ^str1^str2^ rimpiazza str1 con str2 nella prima occorrenza nel precedente comando !n:s/str1/str2/ sostituisce str1 con str2 nella prima occorrenza nell'n-esimo comando, finendo con una sostituzione globale g
Altre informazioni sono descritte nelle pagine man.
Cambiare la propria shell Per cambiare la propria shell si usano generalmente i comandi &man.chsh.1; o passwd -e. Il flag di opzione, qui , può cambiare da sistema a sistema ( su sistemi basati su BSD), quindi verificare le proprie pagine man sul proprio sistema per un uso corretto. Alcune volte questa caratteristica è disabilitata. Se non si riesce a cambiare la propria shell contattare il proprio amministratore di sistema (System Administrator). La nuova shell deve essere un path name assoluto di una valida shell sul sistema. Le shell disponibili variano da sistema a sistema. Inoltre il path name assoluto della shell può cambiare. Normalmente, per la shell Bourne e la shell C sono standard e sono: /bin/sh /bin/csh Alcuni sistemi hanno anche la shell Korn standard normalmente in: /bin/ksh Altre shell, che sono poco popolari e non distribuite normalmente dal venditore di OS, sono &man.bash.1; e &man.tcsh.1;. Queste potrebbero essere situate in /bin o in una directory locale, esempio /usr/local/bin o /opt/local/bin. Se si sceglie una shell non standard del OS, ci si deve assicurare che quella shell e tutte le shell di login disponibili sul sistema siano elencate nel file /etc/shells. Se questo file esiste e la propria shell non è elencata in esso, il demone per il trasferimento di file, &man.ftpd.8;, ti impedirà una connessione ftp su questa macchina. Se tale file non esiste, solamente account con shell standard possono connettersi via &man.ftp.1;. Si può sempre provare una shell prima di settarla come la propria shell di default. Per fare questo si deve digitare il nome della shell che si desidera utilizzare, come qualsiasi altro comando.