[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico] [volume] [parte]
Lo script di shell è un programma molto semplice, che di solito ha solo lo scopo di automatizzare delle operazioni banali, ma ripetitive. Tuttavia, con l'uso di programmi di servizio realizzati appositamente per questi scopi, si possono costruire degli script piuttosto sofisticati con poca fatica.
Se si realizza uno script che deve essere richiamato fornendogli degli argomenti (dei parametri) sotto forma di opzione, come si è abituati con i programmi di servizio comuni, può essere conveniente l'utilizzo di programmi o comandi appositi. Tradizionalmente si fa riferimento a getopt, del quale esistono però diverse interpretazioni; in particolare, la shell Bash fornisce il comando interno getopts (simile, ma non compatibile con getopt), descritto nella sezione 104.4.1. È importante osservare che anche tra una distribuzione GNU/Linux e l'altra ci possono essere differenze tra i programmi di servizio getopt.
Il programma di servizio getopt tradizionale ha la sintassi seguente:
getopt stringa_di_opzioni parametro... |
La stringa di opzioni è un elenco di lettere che rappresentano le opzioni ammissibili; se ci sono opzioni che richiedono un argomento, le lettere corrispondenti di questa stringa devono essere seguite dal simbolo due punti (:). Gli argomenti successivi sono i valori dei parametri da analizzare. Lo scopo del programma è solo quello di controllare che tutto sia in ordine e di mettere a posto ciò che è possibile sistemare, emettendo l'elenco delle opzioni, nel modo «corretto». Per esempio:
$
getopt ab:c -a uno -b due -c tre quattro
[Invio]
Potrebbe restituire il testo seguente:
-a -b due -c -- uno tre quattro |
Infatti, avendo utilizzato la definizione ab:c, è stato stabilito che solo l'opzione -b ha un argomento, per cui, l'argomento uno è stato spostato alla fine delle opzioni, dopo il trattino doppio (--).
Se il programma getopt di cui si dispone è aderente strettamente alle specifiche POSIX, il risultato che si ottiene è diverso, dal momento che la scansione termina nel momento in cui si trova il primo argomento che non riguarda le opzioni:
-a -- uno -b due -c tre quattro |
L'esempio seguente dovrebbe chiarire in che modo si può utilizzare getopt per scandire gli argomenti della riga di comando:
|
In pratica, si comprende che lo scopo di getopt è solo quello di fare un po' di ordine tra le opzioni e di distinguere le opzioni dal resto. Supponendo che il nome dello script sia scansione_1.sh, se si utilizza come nell'esempio già visto, si dovrebbe ottenere il risultato seguente:
$
./scansione_1.sh -a uno -b due -c tre quattro
[Invio]
Opzione a Opzione b, argomento «due» Opzione c Argomenti rimanenti: uno tre quattro |
Se invece getopt è strettamente aderente alle specifiche POSIX, il risultato cambia come segue:
Opzione a Argomenti rimanenti: uno -b due -c tre quattro |
I programmi di servizio Linux si compongono anche di una versione di getopt (1) un po' più evoluta dello standard, che comunque è compatibile con il passato. È ammissibile l'uso della stessa sintassi vista nella sezione precedente e in particolare si può anche forzare l'aderenza alle specifiche POSIX definendo la variabile di ambiente POSIXLY_CORRECT. Questa edizione di getopt è in grado di identificare anche le opzioni «lunghe». Oltre allo schema sintattico già visto, si può utilizzare in particolare quello seguente:
getopt [opzioni_di_getopt] -o|--options stringa_di_opzioni_corte [opzioni_di_getopt] \ |
In pratica, questa versione di getopt può avere delle opzioni per conto proprio, che ne regolano il funzionamento, tra le quali -o è obbligatoria, dal momento che il suo argomento è proprio la stringa che definisce quali opzioni possono essere presenti nei parametri. Eventualmente, per indicare opzioni lunghe, si utilizza l'opzione -l.
La stringa che definisce le opzioni corte, si comporta fondamentalmente come già spiegato nella sezione precedente. In particolare, se si usano due volte i due punti (::), si specifica che l'opzione ha un argomento facoltativo e non obbligatorio. La stringa che definisce le opzioni lunghe è simile a quella delle opzioni corte, con la differenza che, dovendo indicare dei nomi e non solo delle lettere singole, questi sono separati attraverso una virgola; per quanto riguarda l'uso dei due punti, la modalità è la stessa.
Questa versione di getopt ha anche la particolarità di essere in grado di proteggere gli argomenti che ne hanno bisogno, ma per arrivare a questo deve sapere con quale shell si sta operando. Infatti, dal momento che getopt restituisce una stringa che poi deve essere scandita nuovamente, se un argomento contiene caratteri particolari che richiedono una qualche forma di protezione (come gli spazi), è necessario che venga fatta una trasformazione opportuna, che non può essere unica per tutte le situazioni. In condizioni normali, il risultato che si ottiene è adatto per Bash, altrimenti occorre utilizzare l'opzione -s.
Come esempio viene mostrata una variante dello script proposto nella sezione precedente, dove si scandiscono anche le opzioni lunghe e l'ultima ha un argomento facoltativo.
|
Supponendo che il nome dello script sia scansione_2.sh, se si utilizza come nell'esempio seguente,
$
./scansione_2.sh -auno -bdue -ctre quattro
[Invio]
oppure
$
./scansione_2.sh --a-lunga=uno --b-lunga=due --c-lunga=tre
\
\quattro
[Invio]
si dovrebbe ottenere il risultato seguente:
Opzione a Opzione b, argomento «due» Opzione c, argomento «tre» Argomenti rimanenti: uno quattro |
Tuttavia, se utilizzando le opzioni corte, gli argomenti di queste non vengono attaccati alle lettere rispettive, come nell'esempio seguente,
$
./scansione_2.sh -a uno -b due -c tre quattro
[Invio]
gli argomenti facoltativi non vengono presi in considerazione:
Opzione a Opzione b, argomento «due» Opzione c, senza argomenti Argomenti rimanenti: uno tre quattro |
Quando si realizzano degli script, si ha spesso la necessità di realizzare dei file temporanei, magari solo per accumulare il risultato di un'elaborazione senza tentare di fare altri tipi di acrobazie. Il programma di servizio che si usa per queste cose è tempfile: (2)
tempfile [opzioni] |
Nella maggior parte dei casi, tempfile viene usato senza argomenti, ottenendo la creazione di un file vuoto nella directory temporanea (/tmp/
), con permessi normali (lettura e scrittura per tutti, meno quanto filtrato dalla maschera dei permessi), ottenendo il percorso assoluto di questo file dallo standard output.
|
Segue la descrizione di alcuni esempi.
$
tempfile
[Invio]
Crea un file temporaneo e ne restituisce il nome attraverso lo standard output.
|
Quello che si vede è l'esempio tipico di uno script, incompleto, in cui si crea un file temporaneo accumulandone il nome in una variabile di ambiente; quindi si fa qualcosa con quel file (in questo caso si inserisce il risultato del comando ls -l), infine si elimina il file, sempre utilizzando l'espansione della variabile che ne contiene il nome.
In situazioni determinate, può essere importante avviare un programma, o un altro script con un insieme di variabili di ambiente diverso da quello che si erediterebbe normalmente. Per questo si può usare il programma di servizio env: (3)
env [opzioni] comando [argomenti_del_comando] |
Come si può intuire, le opzioni di env servono a eliminare o ad aggiungere delle variabili di ambiente, senza interferire con l'ambiente dello script.
|
A titolo di esempio, si supponga di avere due script: nel primo viene dichiarata la variabile di ambiente CIAO e viene chiamato il secondo eliminando questa variabile dall'ambiente; il secondo script si limita a mostrare il contenuto di questa variabile, se è disponibile.
|
|
Il risultato è che funziona solo la visualizzazione della variabile che avviene con il comando echo del primo script, perché nel secondo non è disponibile. Sarebbe stato diverso se il primo e unico script fosse stato quello seguente:
|
In questo caso, anche se il comando echo viene avviato senza la disponibilità della variabile CIAO, si otterrebbe ugualmente la sua visualizzazione, dal momento che l'espansione della stessa avviene prima della chiamata del programma env.
Spesso, la realizzazione di uno script di shell interattivo, è molto difficile; o meglio, è difficile realizzare qualcosa di pratico da usare. La shell offre il comando interno read, per leggere ciò che viene inserito attraverso la tastiera, ma questo permette di ottenere un'interazione molto banale, a livello di riga di comando. In alternativa si possono usare dei programmi realizzati appositamente per abbellire gli script, come nel caso di dialog.
Di norma, read è un comando interno delle shell POSIX, anche se potrebbe essere disponibile un programma di servizio equivalente, da utilizzare con una shell differente. Il modello sintattico seguente rappresenta una semplificazione che dovrebbe essere compatibile in generale con le shell POSIX:
read [-p invito] [variabile...] |
Il comando read potrebbe essere utilizzato da solo, senza argomenti; in questo caso servirebbe soltanto per attendere la pressione del tasto [Invio], permettendo all'utente di leggere un'informazione che appare sullo schermo, prima di proseguire con altre operazioni.
L'opzione -p dovrebbe essere abbastanza chiara: permette di definire una stringa di invito all'inserimento di qualcosa. Infine, i nomi che vengono collocati in coda alla riga di comando, rappresentano altrettante variabili di ambiente che vengono create appositamente, assegnando loro le parole inserite attraverso read; in particolare, l'ultima variabile dell'elenco raccoglie tutte le parole rimanenti.
|
L'esempio dovrebbe permettere di capire il funzionamento di read. Si osservi in particolare il fatto che l'invito viene ottenuto attraverso il comando echo, utilizzato con l'opzione -n. Supponendo che si tratti dello script read.sh:
$
./read.sh
[Invio]
Inserisci una frase:
ciao come stai? io sto bene
[Invio]
La prima parola inserita è «ciao» La seconda parola inserita è «come» Il resto della frase è «stai? io sto bene» |
La shell Korn e la shell Bash offrono una struttura di controllo particolare, utile per la selezione interattiva di un elemento da un elenco. Si tratta di select, la cui sintassi si riassume nello schema sintattico seguente:
select variabile [in valore...] do lista_di_comandi done |
L'elenco di parole che segue in viene espanso, generando una lista di elementi. L'insieme delle parole espanse viene emesso attraverso lo standard error, ognuna preceduta da un numero. Se in (e i suoi argomenti) viene omesso, vengono utilizzati i parametri posizionali. In pratica è come se venisse usato in $@.
Dopo l'emissione dell'elenco, viene mostrato l'invito contenuto nella variabile PS3 e viene letta una riga dallo standard input. Se la riga consiste del numero corrispondente a una delle parole mostrate, allora viene assegnato alla variabile indicata dopo select la parola corrispondente. Se la riga è vuota (probabilmente è stato premuto soltanto [Invio]), l'elenco e l'invito vengono emessi nuovamente. Se viene letto il codice corrispondente a EOF ([Ctrl d]), il comando termina. Qualsiasi altro valore letto fa sì che la variabile sia posta al valore della stringa nulla. La riga letta viene salvata nella variabile REPLY. La lista di comandi che segue do viene eseguita dopo ciascuna selezione fino a che non viene incontrato un comando break o return.
Il valore restituito da select è quello dell'ultimo comando eseguito all'interno della lista do, oppure zero se nessun comando è stato eseguito.
Viene mostrato nuovamente lo stesso esempio già presentato in occasione della descrizione di select fatta nell'ambito dei capitoli dedicati a Bash: fa apparire un menù composto dagli argomenti fornitigli; a ogni selezione mostra quello scelto.
|
L'esempio seguente proviene dagli script di nanoLinux II 1998 e rappresenta la selezione del nome di un'interfaccia di rete, che viene accumulato nella variabile di ambiente INTERFACCIA:
|
Dialog e altri programmi più o meno compatibili, hanno lo scopo di gestire effetti più appariscenti in uno script di shell, interagendo con l'utilizzatore attraverso schermate colorate e finestre di dialogo, che a seconda dei casi sono adatte allo schermo a caratteri, oppure richiedono la grafica.(4) (5) (6) (7)
dialog [opzioni_generali] [definizione_del_tipo_di_interazione] |
whiptail [opzioni_generali] [definizione_del_tipo_di_interazione] |
Xdialog [opzioni_generali] [definizione_del_tipo_di_interazione] |
gdialog [opzioni_generali] [definizione_del_tipo_di_interazione] |
Si può intuire che il programma «standard» è Dialog, che è fatto per i terminali a caratteri e utilizza la libreria Ncurses.(8) Il programma Whiptail, è una rivisitazione, fatta sempre per i terminali senza grafica, ma usa la libreria Newt. (9) Gli altri programmi si usano con la grafica.
La riga di comando distingue due tipi di opzioni: quelle che hanno valore in senso generale influenzando il comportamento del programma e quelle che definiscono un tipo di interazione con l'utilizzatore. Nella documentazione originale, queste ultime sono definite box-options, perché si riferiscono ai riquadri che vengono mostrati sullo schermo. Evidentemente, si può utilizzare al massimo una sola opzione che definisca una finestra di dialogo.
Dovendo definire delle finestre su uno schermo a caratteri, le opzioni che permettono di descriverle, fanno riferimento a delle dimensioni in caratteri. Questi valori non possono essere omessi e in caso si voglia fare riferimento alle dimensioni ottimali, in base alla disponibilità dello schermo, basta indicare il valore zero, tenendo conto però che questa possibilità non funziona sempre.
La documentazione di Dialog in particolare è accompagnata da esempi di script più completi di quelli che si vedono qui. Vale la pena di studiarli per apprendere bene il funzionamento di questi programmi. In generale, dovrebbero trovarsi a partire dalla directory |
|
|
Gli esempi seguenti mostrano diverse situazioni, dove si mette anche a confronto il risultato che si ottiene tra i vari programmi.
|
In questo script, viene mostrata la finestra di dialogo che si vede nella figura 109.23; in base alla scelta affermativa o negativa, si ottiene la visualizzazione di un messaggio differente.
|
Seguono altre figure, dove si vede l'uso di altri programmi equivalenti.
|
|
Lo script successivo mostrata la finestra di dialogo che si vede nella figura 109.27 e, in base alla scelta del colore, si ottiene il numero corrispondente.
|
Si osservi che è stato evitato l'uso di una lettera accentata, perché alcune delle varie interpretazioni del programma, non sono in grado di gestire altro che la codifica ASCII pura e semplice.
|
|
|
Lo script successivo è una variante di quello precedente in cui si possono selezionare più colori assieme. Nella figura 109.31 si vede la finestra di dialogo che si ottiene.
|
|
|
|
Appunti di informatica libera 2006.07.01 --- Copyright © 2000-2006 Daniele Giacomini -- <daniele (ad) swlibero·org>
1) util-linux: getopt UCB BSD
2) Debianutils: tempfile UCB BSD
3) GNU core utilities GNU GPL
7) Gdialog (Zenity) GNU GPL
8) Ncurses software libero con licenza speciale FSF
Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome strumenti_per_la_realizzazione_di_script_di_shell.htm
[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [translators] [docinfo] [indice analitico]