La shell bash


La shell e' un programma che interpreta i comandi dell'utente. I comandi possono essere dati da terminale, oppure contenuti in file testo (detto script), che viene letto ed eseguito dalla shell. Una shell puo' essere:

La shell di login viene attivata automaticamente all'atto di login. Interpreta prima di tutto uno script uguale per tutti gli utenti e scritto dal sistemista: /etc/profile. Successivamente esegue uno script definito dall'utente, nella propria home directory. Il nome di questo script varia a seconda del tipo di shell.

Per la bash, esegue solo il primo script fra:
~/.bash_profile, ~/.bash_login, ~/.profile
con l'operazione source (spiegata dopo).

L'utente puo' quindi "personalizzare" il suo ambiente di lavoro usando lo script di login. Inoltre, anche alla sua attivazione la shell esegue automaticamente lo script ~/.bashrc , sempre con operazione source.

All'uscita della sessione viene eseguito lo script ~/.bash_logout.

Se uno o piu' di questi script non esistono, non viene dato nessun errore.

~    indica la home directory, e puo' anche essere scritto come $HOME.

Uno script e' dunque una lista di comandi Unix o di shell. Se non specificato altrimenti si suppone che sia la shell sh (che in Linux e' identificata con bash) ad interpretarli. Se si vuole utilizzare un altra shell, si indica sulla prima linea. Per vedere alcune caratteristiche delle diverse shell, leggere shell.txt.

  #! /bin/tcsh
  ......
il carattere "#" in prima colonna, senza "!" dopo indica una riga di commento.

Negli script non si eseguono solo comandi, si possono anche definire delle variabili d'ambiente che possono poi essere riferite nei comandi, premettendo il carattere "$".

Ci sono almeno due modi per eseguire uno script:

  1. dandone semplicemente il nome, con eventuali argomenti. In questo caso viene attivata una nuova shell (sh, tcsh, ksh o altro, come indicato nella prima linea dello script) che esegue i comandi dello script e poi termina (vedi lo schema di esecuzione comandi della sezione Architettura di Unix). Lo script deve essere marcato "eseguibile" attraverso il comando chmod .
  2. attraverso il comando source (abbreviato anche con il carattere ".") seguito dal nome dello script. In questo caso i comandi sono eseguiti all'interno della shell corrente.
Parlando di comandi ci sono diverse possibilita':

Cenni di Grammatica della shell bash

Un pipeline e' un comando o una sequenza di comandi separati dal carattere "|". In questo caso l'output di un comando e' preso come input dal successivo. Vedere esempio in pipe di comandi .

Una lista e' una sequenza di pipeline separati da un operatore fra

 e terminata da uno fra   ;  &  <newline>.

Sia i pipeline che le liste restituiscono un valore di ritorno, =0 oppure =1 in dipendenza dell'operazione effettuata.

E' possibile definire dei compound command come: (i parametri fra [ ] sono opzionali)

# script sh3.sh
# esempio di for aritmetico
for (( i=0; i<4 ; i++))
do echo "valore i $i"
done

ESECUZIONE
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ sh3.sh
valore i 0
valore i 1
valore i 2
valore i 3

Attenzione ai blank, eliminarli puo' causare errore.

E' possibile assegnare delle variabili di tipo stringa di caratteri, poi riferibili nella stessa shell. Una variabile e' assegnata con lo statement
name=[ value ]
Se value e' assente il valore e' la stringa nulla. L'assegnazione e' valida solo nella shell in cui e' eseguita, ma puo' essere esportata nelle shell di livello inferiore con il comando di shell export.
Il comando export da solo lista le variabili esportate, con i valori loro assegnati.
Non mettere blank prima o dopo il carattere =.

ESEMPIO
  export  A=100
  B=1000
  export B
Il nome e il valore di alcune variabili sono predefinite dalla shell, e non possono essere modificate direttamente, altre sono definite come nome, ma non assegnate (sono utilizzate implicitamente da alcuni comandi):

Il comando cd, ad esempio, e' interpretato dalla shell, e riassegna la variabile PWD, utilizzata dal comando pwd.

Quando si da' un comando (o si richiede l'esecuzione di un processo) la shell ricerca il file eseguibile nelle directory indicate nella variabile PATH. Si indicano quindi in sequenza i path assoluti delle directory, separate dal carattere :. Il carattere "." indica la WD generica, cioe' quella in cui ci si trova al momento di dare un comando, non la WD in cui e' eseguito lo script "star". Si consiglia di metterla sempre per ultima.

Alias

Si possono definire nomi diversi per i comandi.

Esempio

alias   del='rm  -i'
alias   dir='ls  -l'
Per l'uso del carattere ', vedere piu' avanti quoting.

Per conoscere la lista degli alias si usa il comando alias senza argomenti.
alias nome da' l'alias definito per quel nome.
Il comando set stampa le variabili che sono state definite.
Il valore di una variabile si referenzia facendola precedere dal carattere $.

Esempio

Nell'esempio sopra si aggiunge (in coda) la directory corrente (i due punti servono da separazione) e la directory $HOME/bin, come directory in cui effettuare la ricerca degli eseguibili. Viene poi stampato il valore di PATH. Si copiano i file main.c e main.h nella directory "./tmp". Se i file non sono presenti nelle directory indicate, lo script termina (exit). Si passa nella sottodirectory "/tmp". Si compone il file tar "main.tar". Si cancellano i file copiati nella WD e si torna nella home directory.

Esempio

#! /bin/bash
# script sh.sh
# eseguire senza "source".
# la variabile B e' visibile nella nuova shell
# non lo e' invece dopo l'exit.
# la variabili A1 non e' mai visibile.
A1=100
echo script sexp   A1 = $A1
export  B=200
echo script sexp   B=$B
/bin/bash   #attiva una nuova shell, da cui si puo' uscire con exit
# fine sh.sh

esecuzione normale
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ sh.sh
script sexp A1 = 100
script sexp B=200
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ echo $A

vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ echo $B
200
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ exit
exit
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$


esecuzione come "source"
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ . sh.sh
script sexp A1 = 100
script sexp B=200
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ exit
exit
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$ echo $A1
100
vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell$

Comandi builtin

Questa e' solo una lista limitata e alcuni comandi sono gia' stati visti prima o nelle sezioni precedenti. Le parentesi quadre indicano parametri opzionali, tranne nel caso del comando test abbreviato.

source nome_script argomenti
alias [ name [ = value ] ... ]
bg [ jobspec ]
fg [ jobspec ]
jobs [ -lnp ] [ jobspec .... ]
cd [ dir ]
kill [ -s sigspec | -sigspec ] [ pid | jobspec ] ...
echo [ -neE ] [ arg ... ]
              Output argomenti separati da blank. Ritorna 0.
exec [ [ - ] command [ arguments ] ]
              Esegue il comando nella shell corrente.
              Senza command puo' avere una redirezione dell'I/O.
exit [ n ]
              Exit dallashell con status = n.
export [ -nf ] [ name [ = word ] ] ....
help [ pattern ]
pwd
read [ -r ] [ name ... ]
             Legge una linea dallo standard input: la prima word e' assegnata al primo name e cosi' via.
set [ ... ] [ arg ... ]
test expr oppure
[ expr ]
             Le parentesi quadre sono in questo caso obbligatorie, come pure il blank di separazione.
             Ritorna 0 o 1 in dipendenza della valutazione di expr.
umask [ -s ] [ mode ]
unalias [ name ... ]
             Rimuove name dalla lista degli alias definiti.
unset [ -fv ] [ name ... ]
              Rimuove la variabile name dall'insieme delle variabili definite.
wait [ n ]
              Aspetta la terminazione del processo o job indicato.

Il comando test e' molto usato, specialmente nella sua forma abbreviata [ expr ]. Si possono ad esempio verificare proprieta' dei file, o uguaglianza di stringhe (non valori numerici).

Alcuni esempi:

test -d file         vero se file esiste ed e' una directory.
test -f file         vero se il file esiste ed e' un file di dati.
test -e file         vero se il file esiste.
test -L file        vero se il file esiste es e' link simbolico.
test -r file         vero se il file esiste ed e' leggibile.
test -x file         vero se il file esiste ed e' eseguibile.
test stringa1 = stringa2       vero se uguali.
test stringa1 != stringa2      vero se diversi.

Il comando   test expr   puo' anche essere scritto come:   [  expre  ]

ESEMPIO

#! /bin/bash 
# script di login 
# attenzione ai blank nella prossima linea 
if [ "$LOGNAME" = "root" ]; then 
     echo " Welcome dear $LOGNAME" 
     if [ -f $HOME/hello ]; 
         then echo $HOME/hello 
     fi 
fi
Esempio
#! /bin/sh 
# script sbh 
if [ "$SHELL" = "/bin/bash" ]; then 
    PS1="sono la shell bash > " 
fi 
# fine
Eseguire lo script sbh come "source sbh". Attenzione ai blank obbligatori.

Parametri posizionali

Sono i parametri della chiamata ad uno script.
Si identificano con il carattere $ seguito dall'indice della posizione. Se si usano numeri di 2 cifre, si racchiudono fra parentesi graffe.

Esempio

nome_script   alfa    10 
$0           $1     $2
Parametri speciali:
  • $0     nome dello script.
  • $@   collezione di tutti i parametri (a partire da $1). Quando si usa all'interno dei doppi apici (vedi quoting piu' avanti) rappresenta l'insieme dei parametri come word separate: "$1" "$2" ... "$n".
  • $*    stringa ottenuta concatenando tutti i parametri in un'unica stringa. I parametri sono separati fra loro dal primo carattere della variabile IFS (normalmente lo spazio). Quindi "$*" indica "$1 $2 $3 .. $n".
  • $#    numero di parametri presenti.
  • $$    processs id della shell.
  • $-    flag opzionali.
  • Esempio

    Prompting

    Il primary prompt PS1 puo' essere modificato run time.
    Ci sono per questo dei caratteri speciali:
       \t   tempo corrente
       \d   data corrente
       \w   current working directory
       \u   username
       \h   hostname
       \#   command number
       \!   history number
       ecc.
    ESEMPIO
       PS1='[\!]\h:\u > '

    Espansioni

    Ci sono diversi tipi di espansioni che vengono effettuate dalla shell prima di attivare i comandi richiesti:
    ESEMPIO
       rm  `find . -name "*.obj"`

    Quoting

    Ci sono altri tipi di apici oltre al ` usato per il command substitution: Esempio
      #! /bin/bash
      echo "numero argomenti = $#"
      for i in $*
      do
         echo  "argomento $i"
      done

    Esempio
      #! /bin/bash
      # script s1
      VAR=`ls`            # lista corta di tutti 
      echo  VAR=$VAR      # i file della WD
      for i in $VAR; do
        ls -ld $i; done   # lista lunga

    Funzione Set

    set [opzioni] [argument-list]
    Senza opzioni mostra solo il nome e il  valore delle variabili di shell. Inoltre setta gli argomenti posizionali ($1, $2 ecc.) con le word in argument-list.  Vediamo alcuni esempi.

    Esempio 1
    Il comando date restituisce la data e l'ora attuale, ed e' costituito da 6 campi (giorno settimana, mese, giorno del mese, ora, tipo di ora e anno).
    Eseguendo lo script

    #!/bin/bash
    date # esegue il comando date
    set $(date) # assegna gli argomenti posizionali
    echo "$@"
    echo "$2 $3, $6"
    si ottiene ad esempio:
    Mon Apr 14 12:47:06 CEST 2008
    Mon Apr 14 12:47:06 CEST 2008
    Apr 14, 2008
    Nota: la notazione $(date) e' una nuova (piu' comado) sintassi per il command substitution.
    Provare ad eseguire la shell:
    #!/bin/bash
    command=pwd
    echo "valore di command: $command."
    command=$(pwd)
    echo "valore di command: $command."

    Esecuzione
    vittoria@krypton:~/didatt/so2/esempiSO2/ScriptShell/bashSO2$ prova.sh
    valore di command: pwd.
    valore di command: /home/vittoria/didatt/so2/esempiSO2/ScriptShell/bashSO2.

    Esempio 2
    #!/bin/bash
    if [ X"$@" = X ]; then
    echo "vuole come argomento il nome di un file"; exit
    fi
    filename="$1"
    set $(ls -il $filename)
    inode="$1"
    size="$6"
    echo
    ( printf "Name Inode Size \n" ; ls -l | echo "$filename $inode $size") | column -t
    Provare ad eseguire dando come parametro il nome di un file della working directory.