Sophie

Sophie

distrib > Mandriva > 9.1 > i586 > by-pkgid > f1098342ec4a2b28475e34123ce17201 > files > 86

howto-html-it-9.1-0.5mdk.noarch.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>Bash Prompt HOWTO: Comandi Esterni</TITLE>
<LINK HREF="Bash-Prompt-HOWTO-4.html" REL=next>
<LINK HREF="Bash-Prompt-HOWTO-2.html" REL=previous>
<LINK HREF="Bash-Prompt-HOWTO.html#toc3" REL=contents>
</HEAD>
<BODY>
<A HREF="Bash-Prompt-HOWTO-4.html">Avanti</A>
<A HREF="Bash-Prompt-HOWTO-2.html">Indietro</A>
<A HREF="Bash-Prompt-HOWTO.html#toc3">Indice</A>
<HR>
<H2><A NAME="s3">3. Comandi Esterni</A></H2>

<H2><A NAME="ss3.1">3.1 PROMPT_COMMAND</A>
</H2>

<P>Bash fornisce un'altra variabile d'ambiente chiamata
<B>PROMPT_COMMAND</B>. Il contenuto di questa variabile viene
eseguito come un normale comando Bash appena prima che Bash visualizzi
il prompt.
<P>
<BLOCKQUOTE><CODE>
<PRE>
[21:55:01][giles@nikola:~] PS1="[\u@\h:\w]\$ "
[giles@nikola:~] PROMPT_COMMAND="date +%H%M"
2155
[giles@nikola:~] d
bin   mail
2156
[giles@nikola:~] 
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>Ci&ograve; che &egrave; accaduto sopra &egrave; che ho cambiato PS1 in
modo da non includere pi&ugrave; la sequenza di escape <CODE>\t</CODE>,
cos&igrave; da visualizzare l'ora in un formato che mi piace di
pi&ugrave;. Ma l'ora compare in una linea diversa dal
prompt. Aggiustando questo con <CODE>echo -n ...</CODE> (come mostrato
sotto) funziona con Bash 2.0+, ma sembra non funzonare con Bash
1.14.7: apparentemente il prompt viene ottenuto in maniera differente
e il metodo seguente causa una sovrapposizione del testo.
<P>
<BLOCKQUOTE><CODE>
<PRE>
2156
[giles@nikola:~] PROMPT_COMMAND="echo -n [$(date +%H%M)]"
[2156][giles@nikola:~]$
[2156][giles@nikola:~]$ d
bin   mail
[2157][giles@nikola:~]$ unset PROMPT_COMMAND
[giles@nikola:~]
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P><CODE>echo -n ...</CODE> controlla l'output del comando <CODE>date</CODE> e sopprime il
carattere newline finale, permettendo al prompt di apparire tutto su
una riga. Alla fine ho usato il comando <CODE>unset</CODE> per rimuovere
la variabile d'ambiente PROMPT_COMMAND.
<P>
<P>Si noti che uso la convenzione $(&lt;comando&gt;) per la sostituzione
dei comandi: ovvero:
<P>
<BLOCKQUOTE><CODE>
<PRE>
$(date +%H%M)
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>significa "sostituisci qui l'output del comando <B>date
+%H%M</B>". Questo funziona in Bash 2.0+. In qualche versione
pi&ugrave; vecchia di Bash, precedente alla 1.14.7, potreste dovere
usare i backquote (<CODE>`date +%H%M`</CODE>). I backquote possono essere
usati in Bash 2.0+, ma stanno venendo via via rimpiazzati in favore di
$(), che si annida meglio. Continuer&ograve; ad utilizzare questa
convenzione in questo documento. Se state usando una versione
precedente di Bash, potete di solito sostituite dei backquote dove
vedete $(). Se la sostituzione di comandi &egrave; preceduta da "\"
(cio&egrave; \$(comando) ), usate dei backslash davanti ad
entrambi i backquote (cio&egrave; \'comando\' ).
<P>
<H2><A NAME="ss3.2">3.2 Comandi Esterni nel Prompt</A>
</H2>

<P>Potete anche usare l'output di normali comandi Linux direttamente nel
prompt.  Ovviamente, non dovrete inserire molto materiale altrimenti
creer&agrave; un prompt molto grande. Dovrete anche inserire un
comando <B>veloce</B>, perch&eacute; verr&agrave; eseguito ogni
volta che il prompt appare sullo schemo e ritardi nell'apparire del
prompt mentre state lavorando possono essere molto
fastidiosi. (Differentemente dall'esempio precedente, a cui assomiglia
molto, questo funziona anche con Bash 1.14.7). 
<P>
<BLOCKQUOTE><CODE>
<PRE>
[21:58:33][giles@nikola:~]$ PS1="[\$(date +%H%M)][\u@\h:\w]\$ "
[2159][giles@nikola:~]$ ls
bin   mail
[2200][giles@nikola:~]$
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>&Egrave; importante notare il backslash prima del segno dollaro della
sostituzione di comando. Senza di esso, il comando esterno viene
eseguito esattamente una volta: quando la stringa PS1 viene letta
nell'ambiente. Per questo prompt, ci&ograve; significherebbe mostrare
lo stesso orario indipendentemente da quanto il prompt viene
utilizzato.  Il backslash protegge il contenuto di $()
dall'interpretazione immediata della shell, cos&igrave; "date" viene
chiamato ogni volta che il prompt viene generato.
<P>
<P>Linux viene fornito con molti piccoli programmi di utilit&agrave; come
<B>date</B>, <B>grep</B>, o <B>wc</B> che consentono di
manipolare informazioni. Se vi trovate a creare complesse combinazioni
di questi programmi all'interno di un prompt, potrebbe essere
pi&ugrave; semplice fare voi stessi uno shell script e chiamarlo dal
prompt. Per assicurare che le variabili della shell siano espanse al
momento giusto negli shell script bash sono spesso necessarie delle
sequenze di escape (come visto sopra con il comando <CODE>date</CODE>):
questo viene elevato ad un altro livello all'interno della linea del 
prompt PS1 ed evitare ci&ograve; creando degli shell script &egrave;
una buona idea. 
<P>
<P>Un esempio di un piccolo shell script usato all'interno di un prompt
viene dato a seguire:
<P>
<BLOCKQUOTE><CODE>
<PRE>
#!/bin/bash
#     lsbytesum - somma il numero di byte in un elenco di directory
TotalBytes=0
for Bytes in $(ls -l | grep "^-" | cut -c30-41)
do
    let TotalBytes=$TotalBytes+$Bytes
done
TotalMeg=$(echo -e "scale=3 \n$TotalBytes/1048576 \nquit" | bc)
echo -n "$TotalMeg"
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>
<P>A volte l'ho usato come una funzione (molto pi&ugrave; efficiente -
sfortunatamente, spiegare in dettaglio le funzioni va oltre lo scopo
di questo documento), altre come uno shell script nella mia 
directory ~/bin, che &egrave; nel mio path. Usata in un prompt:
<P>
<BLOCKQUOTE><CODE>
<PRE>
[2158][giles@nikola:~]$ PS1="[\u@\h:\w (\$(lsbytesum) Mb)]\$ "
[giles@nikola:~ (0 Mb)]$ cd /bin
[giles@nikola:/bin (4.498 Mb)]$
</PRE>
</CODE></BLOCKQUOTE>
<P>
<H2><A NAME="ss3.3">3.3 Cosa Mettere nel Prompt</A>
</H2>

<P>Avrete notato che io metto il nome della macchina, l'ora e la
directory corrente nella maggioranza dei miei prompt. Ad eccezione
dell'ora queste sono cose molto standard da mettere nel prompt, l'ora
&egrave; l'aggiunta pi&ugrave; comune dopo queste. Ma cosa includere nel
prompt &egrave; interamente una questione di gusto personale. Questi
sono esempi da persone che conosco per aiutare a darvi delle idee.
<P>
<P>Il prompt di Dan &egrave; minimale ma efficace, particolarmente per
via del modo in cui funziona.
<P>
<BLOCKQUOTE><CODE>
<PRE>
[giles@nikola:~]$ cur_tty=$(tty | sed -e "s/.*tty\(.*\)/\1/")
[giles@nikola:~]$ echo $cur_tty
p4
[giles@nikola:~]$ PS1="\!,$cur_tty,\$?\$ "
1095,p4,0$ 
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>A Dan non piace avere la directory corrente che pu&ograve;
ridimensionare drasticamente il prompt come ci si muove nell'albero
delle directory, cos&igrave; ne tiene traccia a mente (o digita
"pwd"). Lui ha imparato Unix con csh e tcsh, cos&igrave; usa molto la
command history (qualcosa che molti di noi, viziati da bash, non
facciamo), cos&igrave; la prima cosa nel prompt &egrave; l'history
number. La seconda cosa sono i caratteri significativi del tty
(l'output di "tty" viene tagliato con sed), una cosa che pu&ograve;
essere utile per gli utilizzatori di "screen". La terza cosa &egrave; il
valore di uscita dell'ultimo comando/pipeline (si noti che questo
viene reso inutile da ogni comando eseguito all'interno del prompt -
potreste per&ograve; ottenerlo salvando il valore in una variabile e
rimettendolo poi a posto). In fine, lo "\$" &egrave; un carattere dollaro
per un normale utente e cambia in un cancelletto ("#") se l'utente
&egrave; root.
<P>
<P>Torben Fjerdingstad ha scritto per dirmi che spesso sospende dei
job e poi se ne dimentica, cos&igrave; usa il prompt per ricordarsi
dei job sospesi:
<P>
<BLOCKQUOTE><CODE>
<PRE>
[giles@nikola:~]$ function jobcount {
&gt; jobs|wc -l| awk '{print $1}'
&gt; }
[giles@nikola:~]$ export PS1='\W[`jobcount`]# '
giles[0]# man ls &amp;
[1] 4150

[1]+  Stopped (tty output)    man ls
giles[1]#
</PRE>
</CODE></BLOCKQUOTE>
<P>
<P>Torben usa <B>awk</B> per togliere gli spazi vuoti dall'output di wc,
mentre io avrei usato sed oppure tr - non perch&eacute; siano meglio, ma
perch&eacute; mi sono pi&ugrave; familiari. Vi sono probabilmente
anche altri modi. Torben delimita la stringa PS1 con apostrofi (single 
quote), questo evita che Bash interpreti immediatamente i backquote,
cos&igrave; lui non deve farli precedere da "\" come ho menzionato.
<P>
<P><B>NOTA:</B> C'&egrave; un noto bug in Bash 2.02 che fa s&igrave; che il 
comando <B>jobs</B> (integrato nella  shell) non restituisca nulla ad un 
pipe. Se provate quanto sopra con Bash 2.02, otterrete sempre "0"
indipendentemente da quanti job avete sospesi. Chet Ramey, uno dei
manutentori di Bash, mi dice che questo sar&agrave; corretto in v2.03.
<P>
<H2><A NAME="ss3.4">3.4 Ambiente e Funzioni Bash</A>
</H2>

<P>Come menzionato prima, PS1, PS2, PS3, PS4 e PROMPT_COMMAND sono tutti
salvati nell'ambiente Bash. Per quelli di noi che hanno precedente
esperienza con DOS, l'idea di maneggiare grosse porzioni di codice
nell'ambiente &egrave; terrificante, perch&egrave; l'ambiente DOS era
piccolo e proprio non cresceva bene. Vi sono probabilmente limiti
pratici su cosa pu&ograve; e cosa dovrebbe essere messo nell'ambiente,
ma non so quali siano; stiamo probabilmente parlando di un paio di
ordini di grandezza in pi&ugrave; di quanto gli utenti DOS siano
abituati. Come dice Dan:
<P>
<P>"Nella mia shell interattiva ho 62 alias e 25 funzioni. La mia regola
generale &egrave; che se ho bisogno di qualcosa solamente per uso
interattivo e pu&ograve; essere scritta in bash ne faccio una funzione
(presumendo che non possa essere espressa facilmente con un alias). Se
queste persone hanno problemi di memoria non dovrebbero usare
bash. Bash &egrave; uno dei programmi pi&ugrave; grossi che faccio
girare nella mia Linux box (a parte Oracle). Lancia top qualche volta
e premi 'M' per ordinare per memoria occupata - vedrai quanto bash
&egrave; vicino alla cima della lista. Caspita, &egrave; pi&ugrave;
grosso di sendmail! D&igrave; loro di prendere qualcosa come ash".
<P>
<P>Credo che quel giorno stesse usando solo la consolle: girando X e le
applicazioni X, ho molte cose pi&ugrave; grosse di Bash. Ma l'idea
&egrave; la stessa: l'ambiente &egrave; qualcosa da utilizzare senza
preoccuparsi di riempirlo troppo.
<P>
<P>
<P>Rischio la censura da parte dei guru di Unix quando dico questo (per
crimine di ipersemplificazione): le funzioni sono in pratica piccoli
shell script che vengono caricati nell'ambiente per motivi di
efficienza. Citando ancora Dan: "Le funzioni shell sono efficienti
quanto pi&ugrave; possibile. Approssimativamente &egrave;
l'equivalente di eseguire uno shell script bash/bourne eccetto che
nessun I/O di file &egrave; necessario perch&eacute; la funzione
&egrave; gi&agrave; in memoria. Le funzioni shell sono tipicamente
caricate da .bashrc o .bash_profile a seconda che le si voglia solo
nella shell iniziale o anche nelle sottoshell. Se confronti questo con
l'esecuzione di uno shell script: la shell fa un fork, il processo figlio
apre il file e fa un exec, potenzialmente il path viene esaminato, il
kernel apre il file e esamina sufficienti byte da determinare come
eseguire il file, nel caso di uno shell script una shell deve essere
avviata con il nome dello script come argomento, la shell allora apre
il file, legge e esegue i comandi. Diversamente, con una funzione shell,
tutto fuorch&eacute; l'esecuzione dei comandi pu&ograve; essere
considerato overhead non necessario".
<P>
<HR>
<A HREF="Bash-Prompt-HOWTO-4.html">Avanti</A>
<A HREF="Bash-Prompt-HOWTO-2.html">Indietro</A>
<A HREF="Bash-Prompt-HOWTO.html#toc3">Indice</A>
</BODY>
</HTML>