LEZIONE del 9 Novembre
Poichè la shell di Unix è un linguaggio di programmazione, per
eseguire le istruzioni contenute in uno shell script, è necessario
specificare l'ambiente di esecuzione, ossia come
si propagano i side-effect durante l'esecuzione di
ogni singola istruzione. Pertanto, si deve specificare qual'è l'ambiente
che deve essere attivo prima che inizi l'esecuzione di ogni istruzione.
L'ambiente di esecuzione è determinato dal valore che prendono un certo
numero di variabili associate alla shell e che, per questo, si dicono anche
variabili d'ambiente. L'argomento verrà trattato di seguito ma,
per un riferimento esauriente ed approfondito, si consiglia di consultare il
manuale in
linea della shell bash.
GRAMMATICA DELLA SHELL
Durante l'esecuzione dei comandi di shell l'interprete Bash utilizza il valore
di un certo numero di variabili d'ambiente che possono modificate dalla stessa
esecuzione del comando. Alcune di esse sono assegnate solamente dal sistema
e non possono essere assegnate dall'utente ma, soltanto, lette dalla shell.
Volendo essere precisi fra le variabili d'ambiente ce se sono alcune che non
possono essere assegnate esplicitamente dall'utente. In questo senso si deve
intendere che le seguenti variabili sono assegnate dalla shell:
- PPID
L'ID di processo del genitore della shell.
- PWD
La directory di lavoro corrente come impostata dal comando cd .
- OLDPWD
La precedente directory di lavoro come impostata dal comando cd .
- REPLY
Prende come valore la sequenza di caratteri letti dalla riga di input dal
comando predefinito read, quando non viene passato nessun argomento.
- UID
Si espande nell'ID dell'utente corrente, inizializzata all'avvio della shell.
- EUID
Si espande nell'ID effettivo dell'utente corrente, inizializzato all'avvio
della shell.
- BASH
Si espande nel nome completo usato per chiamare questa istanza della shell bash.
- BASH_VERSION
Si espande nel numero di versione della istanza della shell.
- SHLVL
Incrementato di uno ogni volta che viene attivata una nuova istanza della shell.
- RANDOM
Ogni volta che questo parametro è referenziato, viene generato un
numero intero casuale. La sequenza di numeri casuali può essere
inizializzata assegnando un valore a RANDOM. Se RANDOM viene
eliminato, perde le sue speciali proprietè, perfino se esso viene
successivamente reimpostato.
- SECONDS
Ogni volta che questo parametro è referenziato, viene ritornato il
numero di secondi dalla chiamata della shell. Se un valore viene assegnato
a SECONDS, il valore ritornato in base ai riferimenti successivi è
il numero di secondi trascorsi dall'assegnamento più il valore
assegnato. Se SECONDS viene eliminato, perde le sue speciali
proprietà, perfino se esso viene successivamente reimpostato.
- LINENO
Ogni volta che questo parametro è referenziato, la shell sostituisce
un numero decimale che rappresenta il numero di sequenza della linea corrente
(partendo da 1) dentro uno script o funzione. Quando non in uno script
o funzione, non è garantito che il valore sostituito sia significativo.
Quando in una funzione, il valore non è il numero della linea sorgente
su cui appare il comando (quell'informazione va persa non appena la funzione
viene eseguita), ma è una approssimazione del numero di comandi
semplici eseguiti dalla funzione corrente. Se LINENO viene
eliminato, perde le sue speciali proprietà, perfino se esso viene
successivamente reimpostato.
- HISTCMD
Il numero di storia, o indice nella lista della storia, del comando
corrente. Se HISTCMD viene eliminato, perde le sue speciali
proprietà, perfino se esso viene successivamente reimpostato.
- OPTARG
Il valore dell'ultimo argomento opzione processato dal comando predefinito
getopts.
- OPTIND
L'indice del prossimo argomento che deve essere processato dal comando
predefinito getopts.
- HOSTTYPE
Automaticamente posto a una stringa che univocamente descrive il tipo
di macchina su cui la shell sta girando. Il default dipende dal sistema.
- OSTYPE
Automaticamente posto a una stringa che descrive il sistema operativo
su cui la shell sta girando. Il default dipende dal sistema.
Le seguenti variabili sono usate dalla shell. In alcuni casi, la shell
assegna un valore di default alla variabile; questi casi sono considerati
a parte.
- IFS
L'Internal Field Separator (separatore di campo
interno) che è usato per la suddivisione in parole dopo l'espansione e
per dividere le linee in parole con il comando predefinito read.
Il valore di default è
``<space><tab><newline>''.
- PATH
Il percorso di ricerca dei comandi. Esso è un elenco di directory,
separate da ":", nelle quali la shell cerca i comandi. Il percorso di default
dipende dal sistema ed è assegnato dall'amministratore che installa
la shell. Un valore comune è
``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.''.
- HOME
La home directory dell'utente corrente; l'argomento di default per il
comando incorporato cd.
- CDPATH
Il percorso di ricerca per il comando cd.
Questo è un elenco di directory, separate da ":", nelle quali la shell
cerca la directory di destinazione specificata dal comando cd.
Un valore di esempio è ``.:~:/usr''.
- ENV
Se questo parametro è posto quando la shell sta eseguendo uno script
di shell, il suo valore è interpretato come un nome di file che contiene
comandi per inizializzare la shell, come in .bashrc.
Il valore di ENV è sottoposto ad espansione di parametro, sostituzione
di comando, ed espansione aritmetica prima di essere interpretato come un
percorso. PATH non è usato per cercare il nome risultante.
- MAIL
Se questo parametro è impostato a un nome di file e la variabile
MAILPATH non è impostata, la shell informa l'utente dell'arrivo
di posta nel file specificato.
- MAILCHECK
Specifica quanto spesso (in secondi) la shell controlla la posta. Il default
è 60 secondi. Quando è il momento di controllare la posta, la
shell lo fa prima di dare il prompt. Se questa variabile non è
impostata, la shell disabilita il controllo della posta.
- MAILPATH
Una lista di percorsi di nomi, separati da ":" da usare per il controllo
della posta. Il messaggio che deve essere stampato può essere
specificato separando il percorso dal messaggio con un `?'. $_ sta per
il nome del file di posta corrente. Per esempio:
MAILPATH='/usr/spool/mail/bfox?"You have mail":~/shell-mail?"$_ has mail!"'
La shell fornisce un valore di default per questa variabile, ma la locazione dei
file di posta degli utenti che è usata dipende dal sistema
(adsempio, /usr/spool/mail/$USER).
- MAIL_WARNING
Se è impostata, e viene fatto accesso al file che la shell controlla per
la posta, dopo l'ultima volta che è stato controllato, viene stampato il
messaggio ``The mail in mailfile has been read''.
- PS1
Il valore di questo parametro è espanso e usato come stringa del prompt
primario. Il valore di default è ``bash\$ ''.
- PS2
Il valore di questo parametro è espanso e usato come stringa del
prompt secondario. Il default è ``> ''.
- PS3
Il valore di questo parametro è usato come prompt per il comando
select.
- PS4
Il valore di questo parametro è espanso ed il valore è stampato
prima di ogni comando che la shell mostra durante un trace di esecuzione.
Il primo carattere di IFS è replicato tante volte, quanto
necessario, per indicare livelli multipli di indirezione. Il default è
``+ ''.
- HISTSIZE
Il numero di comandi da ricordare nella storia dei comandi. Il valore di
default è 500.
- HISTFILE
Il nome del file nel quale è salvata la storia dei comandi. Il valore
di default è ~/.bash_history. Se non assegnato, la storia dei
comandi non viene salvata quando una shell interattiva termina.
- HISTFILESIZE
Il numero massimo di linee contenute nel file di storia. Quando a questa
variabile è assegnato un valore, il file di storia è accorciato,
se necessario, per contenere non pi di quel numero di linee. Il valore di
default è 500.
- OPTERR
Se assegnato al valore 1, la shell mostra i messaggi di errore generati dal
comando predefinito getopts. OPTERR è inizializzato ad 1 ogni
volta che è chiamata la shell oppure viene eseguito uno script di shell.
- PROMPT_COMMAND
Se assegnato, il valore è eseguito come comando che precede l'emissione
di ogni prompt primario.
- IGNOREEOF
Controlla l'azione della shell al ricevimento di un carattere EOF
come unico input. Se impostato, il valore è il numero di caratteri
EOF consecutivi digitati come primi caratteri su una linea di input
prima che la shell termini. Se la variabile esiste ma non ha un valore
numerico, o non ha alcun valore, il valore di default è 10. Se essa
non esiste, EOF significa la fine dell'input per la shell. Questo è
valido solo per le shell interattive.
- TMOUT
Se posto a un valore pi grande di zero, il valore è interpretato come
il numero di secondi da aspettare per l'input dopo l'emissione del prompt
primario. Se non arriva l'input la shell termina dopo aver aspettato per
quel numero di secondi.
- FCEDIT
L'editor di default per il comando predefinito fc.
- FIGNORE
Una lista di suffissi, separati da ":", da ignorare quando si effettua
il completamento del nome di file. Un nome di file il cui suffisso combacia
con uno di quelli presenti in FIGNORE è escluso dalla lista
dei nomi di file che combaciano. Un valore di esempio è ``.o:~''.
- INPUTRC
Il nome di file, per il file di avvio di readline che scavalca il default
~/.inputrc.
- notify
Se impostato, la shell informa immediatamente dei job in background
terminati, piuttosto che aspettare fino a prima di stampare il successivo
prompt primario.
- history_control
- HISTCONTROL
Se impostato al valore ignorespace, le linee che iniziano con un
carattere space non sono inserite nella lista della storia. Se
impostato al valore ignoredups, le linee che coincidono con l'ultima
linea della storia non vengono inserite. Il valore ignoreboth
combina le due opzioni.
Se non impostato, o se posto a qualsiasi altro valore diverso da quelli appena
citati, tutte le linee lette dall'analizzatore sono salvate nella lista della
storia.
- command_oriented_history
Se impostato, la shell
tenta di salvare tutte le linee di un comando su pi linee
nella stessa posizione della storia. Questo permette un facile
riediting dei comandi su pi linee.
- glob_dot_filenames
Se impostato, la shell
include i nomi di file che iniziano con un `.' nel risultato della
espansione di percorso.
- allow_null_glob_expansion
Se impostato, la shell permette ai pattern di percorso che non combaciano
con alcun file di espandersi in una stringa nulla, piuttosto che in loro
stessi.
- histchars
I due o tre caratteri che controllano l'espansione della storia
e la tokenizzazione. Il primo carattere è il
.IR "carattere di espansione storia" ,
cioè, il carattere che segnala l'inizio di una espansione della storia,
normalmente `!'.
Il secondo carattere è il carattere di
.IR "sostituzione rapida",
che è usato come scorciatoia per rieseguire il comando precedentemente
inserito, sostituendo una stringa con un'altra nel comando. Il default
è `^'. Il terzo carattere opzionale è il carattere che indica
che il resto della linea è un commento, quando trovato come primo
carattere di una parola, normalmente `#'. Il carattere di commento
della storia fa sì che la sostituzione della storia venga saltata per
le rimanenti parole sulla linea. Esso non provoca necessariamente che
l'analizzatore della shell tratti il resto della linea come un commento.
- nolinks
Se posto, la shell non segue i link simbolici quando esegue dei comandi
che cambiano la directory corrente di lavoro. Essa usa invece la struttura
fisica della directory. Per default, la shell segue la catena logica delle
directory quando effettua comandi che cambiano la directory corrente, come
cd. Si veda anche la descrizione della opzione -P del comando
predefinito set.
- hostname_completion_file
- HOSTFILE
Contiene il nome di un file nello stesso formato di
/etc/hosts
che dovrà essere letto quando la shell ha bisogno di completare un
nome di host. Il file può essere cambiato interattivamente; la prossima
volta che è tentato il completamento del nome di host, la shell
aggiunge il contenuto del nuovo file al database già esistente.
- noclobber
Se impostato, la shell non sovrascrive un file esistente con gli operatori
di ridirezione >, >& e <>.
Questa variabile può essere ignorata quando
si creano file di output usando l'operatore di ridirezione
>| invece di >.
- auto_resume
Questa variabile controlla il modo con cui la shell interagisce con
l'utente ed il job control. Se questa variabile è posta, i comandi
semplici di una singola parola senza ridirezioni sono trattati come
candidati per la ripresa di un esistente job fermato.
Non è permessa alcuna ambiguità: se c'è più di un
job che inizia con la stringa digitata, si seleziona il job più
recente. Il nome di un job fermo, in questo contesto, è la
riga di comando usata per avviarlo. Se impostato al valore exact, la
stringa fornita deve combaciare esattamente con il nome di un job fermo.
Se impostato a substring, la stringa fornita deve combaciare
con una sottostringa del nome di un job fermo. Il valore substring
fornisce funzionalit�analoghe all'id di job %?. Se impostato a
qulsiasi altro valore, la stringa fornita deve essere un prefiso del nome
di un job fermo; questo da funzionalità analoghe all'id di job %.
- no_exit_on_failed_exec
Se questa variabile esiste, una shell non interattiva non terminerà
se non può eseguire il file specificato nel comando predefinto
exec. Una shell interattiva non termina se exec fallisce.
- cdable_vars
Se questa è impostata, un argomento per il comando predefinito
cd che non è una directory è assunto essere il nome
di una variabile il cui valore è la directory su cui andare.
Le precedenti non esauriscono tutte le variabili d'ambiente attive durante
una sessione di lavoro. Per sapere quali sono tutte le variabili assegnate
e il loro valore è sufficiente eseguire il comando printenv.
Gestione della Variabile PATH
Nell'esempio che segue viene proposto uno shell script per la manipolazione
della variabile d'ambiente PATH che mantiene tutti i cammini per le directory
in cui sono contenuti i possibili eseguibili corrispondenti ai comandi di shell.
#!/bin/bash
# path : manipulate the environment variable PATH
# Synopsis : path -<action> [<fullpath>]
#
function Help() {
echo "Synopsis: path -<action> [<fullpath>]"
echo "Available actions"
echo " i: add the given path as first"
echo " a: add the given path as last"
echo " d: if found delete the given path"
echo " l: list all the searching path"
echo " ?: this screen"
}
function Display() {
OLDIFS=$IFS
IFS=":"
WA=`echo $CSP`
IFS=$OLDIFS
K=0
for path in $WA
do
K=`expr $K + 1`
echo "[$K]=$path"
done
}
if [ $# -eq 0 ]
then
Help;
exit 2
fi
BASH_PROFILE="$HOME/.bash_profile"
CSP=$PATH
CHG=1
if [ `echo $1 | egrep -e "-"` ] > /dev/null
then
ACTION=`echo $1 | sed "s/-//"`
case $ACTION in
a) if [ -n "$2" ]
then
CSP="$2:$CSP" ;
CHG=0 ;
Display
fi ;;
i) if [ -n "$2" ]
then
CSP="$CSP:$2" ;
CHG=0 ;
Display
fi ;;
d) if [ `echo $CSP | grep -e "^$2:"` ] > /dev/null
then
CSP=`echo $CSP | sed -e "s|^$2:||"` ;
elif [ `echo $CSP | grep -e ":$2:"` ] > /dev/null
then
CSP=`echo $CSP | sed -e "s|:$2:|:|"` ;
else
CSP=`echo $CSP | sed -e "s|:$2|:|"` ;
fi
CHG=0 ;
Display ;;
l) Display ;;
?) Help ;;
*) echo "illegal command" ;;
esac
else
echo "no action given"
exit 1
fi
if [ $CHG -eq 0 ]
then
echo -n "Do you want to use the new search path? (y/n) "
read YES
if [ "$YES" == "y" ]
then
PATTERN="PATH=$CSP"
sed -e "s/^PATH/PATH=\n#PATH/" $BASH_PROFILE >> tmp$$;
sed -e "s|^PATH=|$PATTERN|" tmp$$ > $BASH_PROFILE;
/bin/rm -f tmp$$;
echo "done"
export PATH
exec /bin/bash -l
fi
fi
exit 0
|
Gestione della Variabile PATH
Si osservi che per rendere effettive le modifiche apportate alla suddetta
variabile PATH è necessario ritornare alla shell "sostituendo
l'esecuzione di path con quella della shell con la
modalità di login".
L'Agenda Telefonica Rivisitata
Nella precedente lezione si è visto come realizzare il passaggio dei
parametri dalla pagina HTML alla shell che attiva lo script CGI che esegue
l'azione richiesta dalla pagina HTML. Si osserva che tale indicizzazione
è ottenuta mediante l'attributo action associato
al tag form.
Il meccanismo con il quale la shell accede ai suddetti parametri è
realizzato introducendo alcune variabili di shell che sono:
- REQUEST_METHOD,
con la quale viene stabilito il metodo con cui i parametri sono
effettivamente "imbustati" e raggiungono la shell;
- CONTENT_LENGTH,
necessaria per l'identificazione della stringa quando questa viene
inoltrata in testa al messaggio;
- QUERY_STRING,
che viene assegnata solamente se si utilizza il metodo get.
A questo punto risulta relativamente semplice estrarre i suddetti parametri,
se si conosce il modo con il quale è realizzata l'associazione
parametro-valore. Nella
scorsa lezione l'estrazione dei parametri è stata ottenuta parametro
per parametro utilizzando la funzione Get_arg().
Lo script proposto di seguito mostra come ottenere i parametri della pagina
HTML automaticamente mediante un'unica chiamata allo script cgiparse
con una sintassi simile a quella utilizzata dal server Roxen.
#!/bin/bash
# Synopsis : eval `cgiparse -init`
# extraction of the parameters passed to the shell by an HTML page
PREFIX="FORM_"
function DoParse() {
IFSOLD=$IFS;
IFS="&";
for ARG in $1
do
J=0;
IFS="=";
for ITEM in $ARG
do
VALUE="";
if [ "$J" = 0 ]; then
NAME="$ITEM"
else
VALUE="$ITEM"
fi ;
let "J = $J + 1";
done
IFS="&";
echo "${PREFIX}$NAME=${VALUE}";
done
IFS=$IFSOLD;
}
if [ `echo $1 | egrep -e "-"` ] > /dev/null; then
ACTION="`echo $1 | sed s/-//`"
else
echo "no action to execute";
exit 2
fi
if [ "$REQUEST_METHOD" = POST ]; then
QUERY_STRING=$( head --bytes="$CONTENT_LENGTH" );
fi
case $ACTION in
init) DoParse "${QUERY_STRING}"; exit 0 ;;
form) exit 0 ;;
*) echo "no such an option"; exit 2 ;;
esac
|
CGI parsing per il server Apache
La variabile PREFIX consente, fra l'altro di
caratterizzare il nome dei parametri anteponendone un prefisso; naturalmente
il prefisso può essere impostato alla stringa vuota. L'esecuzione
dello script è molto semplice. Per mezzo delle variabili d'ambiente
si estrae la stringa dei parametri e, quindi, modificando la variabile
d'ambiente IFS che codifica la separazione dei
campi, alternativamente come caratteri "&" e "=",
si ottiengono le istanziazioni dei parametri ai valori passati che sono
stati passati alla form dalla pagina HTML.
Per completezza nel seguito è riportata la pagina che viene eseguita
in seguito al
rendering della pagina HTML che consente l'accesso alla propria agenda
telefonica.
#!/bin/bash
echo "Content-type: text/plain"
echo
export REQUEST_METHOD
export QUERY_STRING
export CONTENT_LENGTH
WWW="/home/fedora/antonio/www"
EXAMPLES="${WWW}/LabOS/2006/lessons/examples"
CGI="${EXAMPLES}/phonebook/cgiparse"
eval `$CGI -init`
eval `$CGI -form`
echo "Surname=$FORM_Surname"
echo "Name=$FORM_Name"
echo "Street=$FORM_Street"
echo "Number=$FORM_Number"
echo "City=$FORM_City"
echo "Code=$FORM_Code"
echo "Phone=$FORM_Phone"
echo "Action=$FORM_Action"
exit 0
|
Passaggio dei parametri effettuato dal CGI
La riga eval `$CGI -init` compare solo per compatibilità con
l'analogo script per il server Roxen ma non ha alcun effetto come risulta
dal codice implementativo dello script.