| Guida avanzata di scripting Bash: Un'approfondita esplorazione dell'arte dello scripting di shell | ||
|---|---|---|
| Indietro | Capitolo 33. Miscellanea | Avanti |
Può uno script richiamare sé stesso ricorsivamente? Certo.
Esempio 33-8. Un (inutile) script che richiama sé stesso ricorsivamente
#!/bin/bash
# recurse.sh
# Può uno script richiamare sé stesso ricorsivamente?
# Sì, ma può essere di qualche uso pratico?
# (Vedi il successivo.)
INTERVALLO=10
VALMAX=9
i=$RANDOM
let "i %= $INTERVALLO" # Genera un numero casuale compreso
#+ tra 0 e $INTERVALLO - 1.
if [ "$i" -lt "$VALMAX" ]
then
echo "i = $i"
./$0 # Lo script genera ricorsivamente una nuova istanza
#+ di sé stesso.
fi # Ogni script figlio fa esattamente la stessa
#+ cosa, finché $i non diventa uguale a $VALMAX.
# L'uso di un ciclo "while", invece della verifica "if/then", provoca problemi.
# Spiegate perché.
exit 0
# Nota:
# ----
# Lo script, per funzionare correttamente, deve avere il permesso di esecuzione.
# Questo anche nel caso in cui venga invocato con il comando "sh".
# Spiegate perché. |
Esempio 33-9. Un (utile) script che richiama sé stesso ricorsivamente
#!/bin/bash
# pb.sh: phone book
# Scritto da Rick Boivie e usato con il consenso dell'autore.
# Modifiche effettuate dall'autore de Guida ASB.
MINARG=1 # Lo script ha bisogno di almeno un argomento.
FILEDATI=./phonebook
# Deve esistere un file dati di nome "phonebook"
#+ nella directory di lavoro corrente.
NOMEPROG=$0
E_NON_ARG=70 # Errore di nessun argomento.
if [ $# -lt $MINARG ]; then
echo "Utilizzo: "$NOMEPROG" filedati"
exit $E_NON_ARG
fi
if [ $# -eq $MINARG ]; then
grep $1 "$FILEDATI"
# 'grep' visualizza un messaggio d'errore se $FILEDATI non esiste.
else
( shift; "$NOMEPROG" $* ) | grep $1
# Lo script richiama sé stesso ricorsivamente.
fi
exit 0 # Lo script termina qui.
# Quindi, è corretto mettere
#+ dati e commenti senza il # oltre questo punto.
# -------------------------------------------------------------------------
# Un estratto del file dati "phonebook":
John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333
Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232
Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678
Zoe Zenobia 4481 N. Baker St., San Francisco, SF 94338 (415) 501-1631
# -------------------------------------------------------------------------
$bash pb.sh Roe
Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678
$bash pb.sh Roe Sam
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678
# Quando vengono passati più argomenti allo script,
#+ viene visualizzata *solo* la/e riga/he contenente tutti gli argomenti. |
Esempio 33-10. Un altro (utile) script che richiama sé stesso ricorsivamente
#!/bin/bash # usrmnt.sh, scritto da Anthony Richardson # Utilizzato con il permesso dell'autore. # utilizzo: usrmnt.sh # descrizione: monta un dispositivo, l'utente cho lo invoca deve essere elencato # nel gruppo MNTUSERS nel file /etc/sudoers. # -------------------------------------------------------------------- # Si tratta dello script usermount che riesegue se stesso usando sudo. # Un utente con i permessi appropriati deve digitare semplicemente # usermount /dev/fd0 /mnt/floppy # invece di # sudo usermount /dev/fd0 /mnt/floppy # Utilizzo questa tecnica per tutti gli #+ script sudo perché la trovo conveniente. # -------------------------------------------------------------------- # Se la variabile SUDO_COMMAND non è impostata, significa che non lo si #+ sta eseguendo attraverso sudo, che quindi va richiamato. Vengono passati #+ i veri id utente e di gruppo . . . if [ -z "$SUDO_COMMAND" ] then mntusr=$(id -u) grpusr=$(id -g) sudo $0 $* exit 0 fi # Verrà eseguita questa riga solo se lo si sta eseguendo con sudo. /bin/mount $* -o uid=$mntusr,gid=$grpusr exit 0 # Note aggiuntive (dell'autore dello script): # ------------------------------------------------- # 1) Linux consente l'uso dell'opzione "users" nel file /etc/fstab, # quindi qualsiasi utente può montare un certo dispositivo. # Ma, su un server, è preferibile consentire l'accesso ai dispositivi # solo a pochi individui. # Trovo che usare sudo dia un maggior controllo. # 2) Trovo anche che, per ottenere questo risultato, sudo sia più # conveniente che utilizzare i gruppi. # 3) Questo metodo fornisce, a tutti coloro dotati dei corretti permessi, # l'accesso root al comando mount, quindi fate attenzione a chi lo # concedete. # È possibile ottenere un controllo ancora più preciso # utilizzando questa tecnica in differenti script ciascono inerente a # mntfloppy, mntcdrom e mntsamba. |
![]() | Troppi livelli di ricorsività possono esaurire lo spazio di stack dello script, provocando un segmentation fault. |