dal 2015 - visita n. 675
Seminario.13
Seminario.13

 

La Shell (parte 2)


La shell Bash, similmente alle altre disponibili in Linux, non solamente permette la digitazione sequenziale dei comandi, ma essendo dotata di un vero e proprio mini linguaggio di programmazione permette di codificare degli script con tanto di strutture di controllo e sequenze di istruzioni. Moltissimi dei programmi che normalmente si utilizzano in Linux sono, in effetti, script di shell e pertanto per comprenderne il funzionamento ed eventualmente modificarli e' indispensabile conoscere le basi del linguaggio e la sua sintassi.

Incidentalmente si sottolinea la differenza tra linguaggi compilati e linguaggi di scripting (interpretati): i primi sono molto piu' veloci e potenti, ma spesso questa velocita' e potenza non giustifica la complessita' ed il tempo necessario per il loro sviluppo (C, Fortran, Pascal, Cobol), i secondi sono piu' lenti, ma facilmente e velocemente modificabili dal momento che sono costituiti solo da semplici file di testo, ottimi per le piccole applicazioni. Altri esempi di linguaggi interpretati sono Html, Perl, Lisp, Tcl.

Per scrivere semplici programmi interpretabili dalla shell e' richiesta la conoscenza di almeno i principali comandi di Linux, e la capacita' di usare un editor di testo, non necessariamente visuale (anzi!) come mcedit, vim, pico, o joe. E' anche buona abitudine non provare i propri script come utente root per evitare spiacevoli danni ai file di sistema.



Primo esempio

Secondo una tradizione classica pare che non si possa prescindere dal sapere preparare un programma che stampi a video l'ignobile frase "Ciao mondo !", e pertanto ecco la ricetta in tre passi:

  1. aperto il proprio editor di testo preferito si scriverà e si salverà quanto segue


    #!/bin/bash echo "Ciao mondo !"

    la prima riga, indispensabile, avvisa Linux che vogliamo che tutto cio' che segue sia passato all'interprete bash, che in questo caso si trova nella directory /bin ma che trovandosi in un posizione non standard si indicherà con il percorso appropriato.
  2. Una volta salvato lo script col nome di ciao.sh si dovrà renderlo eseguibile impostando il permesso appropriato:

    chmod o+x ciao.sh
    

    in questo caso si è aggiunto il permesso di esecuzione +x ai permessi del proprietario (owner) del file ciao.sh e tanto basta per rendere eseguibile, agli occhi di Linux, il file in questione. Il suffisso .sh utilizzato non implica infatti nessuna caratteristica di eseguibilità per il file serve solo all'utente nel caso in cui desideri identificare facilmente una determinata categoria di file. L'esempio visto funzionerebbe egualmente anche chiamando il file semplicemente ciao.
  3. A questo punto occorrerà provare il programma avviandolo con

    ./ciao.sh 

Se tutto è andato a buon fine sul video si vedrà il messaggino "Ciao mondo !" che è il risultato della classica sequenza:

    scrittura-salvataggio-permessi-prova

Nel caso di eventuale insuccesso con rientro nell'editor per le correzioni del caso non sarà ovviamente più necessario reimpostare il permesso di esecuzione.



Secondo esempio

Scriveremo adesso un programma che spostera' tutti i file della directory corrente dentro una directory appoggio appo che dovrà essere creata, cancellera' quindi la directory appo e tutti i file al suo interno, ed alla fine la ricreera' di nuovo. Tutto cio' preparando il seguente script di comandi:


#!/bin/bash mkdir appo mv * appo rm -rf appo mkdir appo echo "Lavoro eseguito correttamente"

che verrà prima salvato con il nome di test.sh, poi gli sarà assegnato il permesso di esecuzione con chmod ed infine verrà eseguito digitando ./test.sh. Ecco quindi come compiere azioni ripetitive con poche righe di script.



Terzo esempio

Questo esempio trae la sua origine dalla necessità reale di riconfigurare periodicamente le impostazioni di rete su una workstation del laboratorio anche da parte di personale non esperto.


#!/bin/bash clear echo "Laboratorio Aula 13 - Impostazione Standard a 192.168.12.3"; echo "----------------------------------------------------------"; # Definizione Variabili IPADDR=192.168.12.76 GATEWAY=192.168.12.3 NETMASK=255.255.255.0 NETWORK=192.168.12.0 BROADCAST=192.168.12.255 DNS1=151.99.125.2 DNS2=212.216.112.112 # Attivazione Scheda rete locale ifconfig eth0 inet down ifconfig eth0 inet up ${IPADDR} netmask ${NETMASK} broadcast ${BROADCAST} route add -net 0.0.0.0/0 gw ${GATEWAY} echo "nameserver "${DNS1} > /etc/resolv.conf echo "nameserver "${DNS2} >> /etc/resolv.conf # Visualizza Situazione ifconfig eth0 route cat /etc/resolv.conf

Oltre all'uso normale di echo, già visto in precedenza, si può notare il suo utilizzo con la ridirezione dell'output sia per aggiungere una stringa ad un file (con >>) sia per creare un file contenente una stringa (con >). E ancora si osservi: la presenza di clear, per la pulizia dello schermo, la definizione delle VARIABILI, l'uso delle stesse tramite la struttura ${}, le righe di commento contrassegnate da #.



Strutture di controllo

Un vero linguaggio di programmazione dispone soprattutto di strutture di controllo, Bash non fa eccezione e infatti dispone di tutto il necessario per permettere ai programmi: di prendere delle decisioni, di essere molto piu' compatti ed eleganti, e sopratutto di gestire gli eventuali errori. Gli esempi riportati finora hanno fornito all'interprete una serie di istruzioni da eseguire in sequenza. Se adesso si crea uno script chiamato test1.sh contenente i seguenti comandi:


#!/bin/bash cp /etc/miofile . echo "Copiato."

Il programma dovrebbe copiare il file /etc/miofile nella directory corrente e stampare a video la stringa "Copiato.". Il programma però funzionera' a condizione che esista un file chiamato miofile nella directory /etc, altrimenti si otterrà dalla shell una risposta del tipo:

cp: /etc/miofile: No such file or directory
Copiato.

Sarebbe meglio se il programma verificasse l'esistenza di /etc/miofile prima di provare a copiarlo.

Bash mette a disposizione i seguenti costrutti di controllo: if, while, until, for, case. Ogni struttura di controllo necessita di un comando di apertura e uno di chiusura, un po' come i tag in html. Per esempio la struttura di controllo che inizia con if viene chiusa con fi. L'esempio precedente può allora essere riscritto come segue:


#!/bin/bash if test -f /etc/miofile then # il file esiste cp /etc/mia_var . echo "Copiato." else # il file non esiste echo "il file non esiste" exit fi

Si noti che la seconda riga, con il comando test che verifica l'esistenza del file /etc/miofile, può essere riscritta, con una sintassi alternativa, come segue:

if [ -f /etc/miofile ];

nella quale sono da evidenziare i due spazi, obbligatori, tra le parentesi quadre; tutto quello che si trova dopo il punto e virgola viene interpretato come si trovasse su una riga a se' stante.

L'indentazione non e' obbligatoria ma rende il codice piu' leggibile, aiutando a separare i blocchi di istruzioni.

I controlli che la shell ci permette di fare su di un file sono i seguenti:

-d verifica se il file e' una directory
-e verifica se il file esiste
-f verifica se il file e' un file regolare
-g verifica se il file ha il bit SGID settato
-r verifica se il file e' leggibile da chi esegue lo script
-s verifica se la dimensione del file non e' 0
-u verifica il file ha il bit SUID settato
-w verifica se il file e' scrivibile

Il costrutto else viene usato per indicare al programma l'azione da compiere se la condizione non e' soddisfatta, mentre il costrutto elif, somma dei costrutti else e if permette di evitare un susseguirsi di if quando si vogliono testare piu' condizioni. Quando si vuole testare una variabile e' buona norma includerla dentro doppie virgolette, affinche' venga espansa correttamente, ad esempio:

if [ "$mia_variabile" -eq 5 ]; then 



La Shell (parte 2)
// Applicativi (parte 5)
// Free Software
// ... Continua




// Lucidi 04 PDF



L'uomo può quanto sa.
Francesco Bacone

Valid CSS!
pagina generata in 0.001 secondi