Con un approccio pratico, e ricco di esempi semplici per illustrare bene i concetti, impara le basi del linguaggio di scripting Bash, ormai divenuto uno standard de facto in termini di scripting di shell (Shell Scripting).
La presentazione si compone di 12 lezioni / capitoli:
1 - Introduzione
2 - Primi passi
3 - Variabili
4 - Array
5 - Aritmetica
6 - Test
7 - Costrutti condizionali
8 - Cicli iterativi
9 - Funzioni
10 - Quoting
11 - Terminare uno script
12 - Debugging
Per un totale di 98 diapositive
3. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°1
1.
Introduzione
● Shell
● Comandi della shell
● Bash script
● Shell scripting
● Perché programmare la shell?
3
4. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione
shell
Interprete di comandi che permette
all’utente di comunicare col sistema
operativo attraverso una serie di
funzioni predefinite, o di eseguire
programmi e script.
4
6. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione
In questa presentazione esploreremo le basi
dello scripting di shell, e per farlo ci baseremo
sulla shell Linux più diffusa, cioè Bash.
6
7. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione7
Comandi della shell
Nella shell di Linux (Bash) possiamo eseguire tre distinti elementi:
❏ Oggetti eseguibili: comandi di shell (come ad esempio ls) per cui
esiste un relativo file eseguibile nelle directory predefinite di sistema;
❏ Comandi built-in: comandi incorporati nella shell (come cd, echo);
❏ Script: programmi scritti in linguaggio bash script che possono
contenere sia comandi built-in che oggetti eseguibili.
8. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione8
Bash script
Bash offre una sintassi ricca, tale da
permettere la creazione e l’esecuzione di
sequenze di comandi della shell,
tecnicamente chiamate Bash script.
Bash Script
Script
File testuale che può contenere un elenco di
comandi, così come variabili, funzioni,
strutture di controllo di flusso e tutti gli altri
costrutti tipici della programmazione.
9. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione
Shell Scripting
In definitiva, un Bash script è uno script
scritto nel linguaggio di scripting nativo
messo a disposizione dalla shell Bash.
L’arte di creare e modificare gli script della
shell prende il nome di Shell Scripting.
9
10. Matteo Collica - Shell Scripting (#!/bin/bash) - Introduzione
Usi comuni
I bash script vengono comunemente usati
per automatizzare molte attività di
amministrazione di sistema, come l’analisi
dei log e il backup dei dischi. Sono anche
molto usati come script di installazione
per programmi complessi.
Perché Programmare la Shell?
L’Importanza di saperlo fare
Gli script permettono di risolvere problemi
complessi con istruzioni semplici. Ad esempio,
solo una riga per richiamare un programma
esterno; al tempo stesso, la shell ci mette a
disposizione pressoché tutta la potenza di un
linguaggio di programmazione completo.
10
11. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°2
2.
Primi passi
● Sintassi del linguaggio
● Eseguire uno script
11
12. Matteo Collica - Shell Scripting (#!/bin/bash) - Primi passi12
La prima riga dello script indica al sistema che il file deve essere
eseguito da /bin/bash, che corrisponde al percorso standard
dell’interprete BASH su qualsiasi sistema basato su Unix.
Sintassi del Linguaggio
13. Matteo Collica - Shell Scripting (#!/bin/bash) - Primi passi
Eseguire uno Script
chmod +rx ./script.sh
13
14. Matteo Collica - Shell Scripting (#!/bin/bash) - Primi passi
Eseguire un Bash Script
❖ $sh <nome script> ignora le estensioni specifiche di Bash e, di
conseguenza, potrebbe compromettere l’esecuzione.
➢ Una possibile alternativa è $bash.
❖ È necessario il permesso di lettura perché la shell per poter eseguire
uno script deve essere prima in grado di leggere il file che lo contiene.
❖ È necessario specificare il percorso completo (se non fa parte di
quelli listati nella variabile $PATH) di uno script per eseguirlo.
➢ Esempio - per la directory corrente: ./<nomescript>.
14
17. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
Variabili
Esistono due diversi tipi di variabili:
● Variabili locali: vengono dichiarate dal programmatore ed utilizzate
all’interno dello script, le chiameremo per semplicità solo “variabili”;
● Variabili predefinite: sono definite dal sistema ed utilizzabili per
ottenere informazioni, un esempio è $PATH che contiene i percorsi
delle directory in cui il sistema cerca i file eseguibili, ne vedremo
alcune particolarmente utili per gli script qualche slide più avanti.
17
18. 18
Per dichiarare una variabile è sufficiente assegnarle un valore
Per assegnare un valore ad una variabile: <nome>=<valore>
Per leggere il valore di una variabile: $<nome>
Sintassi
Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
20. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
Bash – come Perl o PHP – è un
linguaggio a tipizzazione dinamica:
le variabili non possiedono un tipo
vero e proprio, ma vengono
“convertite” in base al contesto.
Tipizzazione
Qualunque valore viene di fatto
memorizzato come stringa, ma
funzioni che richiedono numeri in
input possono comunque
trattarle come tali.
20
22. 22
Il builtin read legge una riga dallo standard
input e la memorizza nella variabile fornita
come parametro
Input
Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
23. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili23
Valore Predefinito?
In Bash non è obbligatorio dichiarare le variabili. Se però si
cerca di leggere il contenuto di una variabile non dichiarata, si
otterrà semplicemente una stringa vuota, senza che venga
generato alcun messaggio di errore.
24. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
Valore Predefinito
È possibile specificare un valore da utilizzare nel caso in cui la
variabile non sia stata dichiarata per mezzo dell’operatore “:-”
24
26. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
Valore Predefinito
Esiste anche l’operatore ":=", che imposta un
valore alla variabile se questa non è definita
26
27. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili
Argomenti
Gli stessi script Bash sono programmi che
possono essere eseguiti; anch’essi perciò
possono accettare degli argomenti.
Variabili Predefinite
Parametri posizionali
Gli argomenti sono disponibili in un
programma come parametri posizionali,
simili alle variabili ma identificati da
numeri ($1, $2... etc).
27
28. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili28
I parametri posizionali successivi al nono ($9) invece
richiedono l’espansione con l’uso delle parentesi graffe; per
riferirsi al decimo parametro, ad esempio, si dovrà indicare
${10}, altrimenti $10 verrebbe interpretato come ${1}0.
Parametri Posizionali
29. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili29
Il numero di parametri posizionali è memorizzato in
$#, ed è possibile stampare una stringa contenente
tutti i parametri utilizzando la variabile predefinita $*
Parametri Posizionali
30. Matteo Collica - Shell Scripting (#!/bin/bash) - Variabili30
Altre Variabili Predefinite
$$
Memorizza il PID (Process IDentifier) della shell in
esecuzione. Spesso inclusa nei nomi dei file
temporanei generati da uno script, come
/tmp/script.$$, se più istanze dello script
possono essere eseguite allo stesso tempo.
$!
Corrisponde al PID dell’ultimo processo eseguito
in background. Utile per tenerne traccia mentre
questo continua a svolgere il proprio lavoro.
IFS
Internal Field Separator, rappresenta il carattere (o i
caratteri) che separa i diversi parametri fra di loro. Il
valore predefinito è ‘SPACE TAB NEWLINE’.
Alcune variabili utili per gli script
$? contiene lo stato di uscita dell’ultimo comando eseguito,
consiste in un valore intero positivo compreso tra 0 e 255;
$0 contiene il nome dello script;
$USER contiene il nome dell’utente che esegue lo script;
$LINENO contiene il numero di riga corrente nello script.
32. Matteo Collica - Shell Scripting (#!/bin/bash) - Array
array
Un array è una collezione ordinata di valori che possono essere
richiamati univocamente tramite indici numerici (a partire da 0).
Qualsiasi variabile può essere utilizzata come vettore. Non esiste un
limite massimo alla dimensione di un array, e non è necessario
indicizzare o assegnare gli elementi in modo contiguo.
32
33. Matteo Collica - Shell Scripting (#!/bin/bash) - Array33
Inizializzazione
Per definire un array possiamo ricorrere
a 3 diversi metodi di inizializzazione.
37. Matteo Collica - Shell Scripting (#!/bin/bash) - Array
Array: Riepilogo Sintassi
❏ array[@] o array[*] per fare riferimento all’intero contenuto;
❏ #array[@] o #array[*] per conoscere il numero di elementi.
❏ array[@]:x:y per accedere a y elementi di indice da x in poi;
❏ array[x]:y:z per accedere a z caratteri a partire dal numero y
dell’elemento di indice x.
❏ unset array[x] per rimuovere l’elemento di indice x;
❏ unset array per eliminare un array.
37
39. Matteo Collica - Shell Scripting (#!/bin/bash) - Aritmetica
Aritmetica
Le operazioni aritmetiche seguono lo stile dei linguaggi derivati
dal C, ma Bash supporta soltanto l’aritmetica intera.
Numeri decimali causerebbero un errore di sintassi e i risultati
delle divisioni sono quelli dati dalla divisione intera.
39
40. Matteo Collica - Shell Scripting (#!/bin/bash) - Aritmetica
Espansione Aritmetica
➔ Sintassi: $(( <espressione> ))
➔ Operatori classici: +, -, *, /
➔ Operatore di modulo (resto della divisione intera): %
➔ Operatore di assegnazione: =
➔ Operatori composti: +=, -=, *=, /=, %=
➔ Operatore di esponenziazione: **
➔ Operatori di incremento e decremento: ++, --
➔ Operatore -() per invertire il segno di un espressione
40
42. Matteo Collica - Shell Scripting (#!/bin/bash) - Aritmetica
Variabili
All’interno di un’espressione aritmetica è possibile riferirsi a variabili
dichiarate precedentemente nello stesso script.
❖ Omettendo $ ci si può riferire al valore di una variabile;
❖ Specificando $ viene effettuata una sostituzione di stringa.
42
43. Matteo Collica - Shell Scripting (#!/bin/bash) - Aritmetica
Espressioni Aritmetiche
➔ Un’espressione aritmetica può formare anche un comando a sé
stante, usando la sintassi: (( variabile = <espressione> ))
➔ Operatore di separazione in sotto-espressioni: ,
◆ separa in diverse sotto-espressioni da valutare distintamente; il valore finale
sarà quello dell’ultima sotto-espressione valutata.
➔ Operatori di confronto intero <, >, <=, >=, ==, !=
◆ Ciascuno viene valutato come 1 se “vero” o 0 se “falso”.
➔ Operatori di logica booleana: !, &&, ||
➔ Operatore condizionale: ?
43
45. Matteo Collica - Shell Scripting (#!/bin/bash) - Aritmetica
Aritmetica Non Intera
Per includere i numeri decimali possiamo ricorrere a tool esterni,
come la utility bc (per ulteriori informazioni consultare $man bc):
45
46. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°6
6.
Test
● Confronto tra interi
● Confronto tra stringhe
● Test su file
● Nuova sintassi
46
47. Matteo Collica - Shell Scripting (#!/bin/bash) - Test
Test
Permette di confrontare valori e controllare i tipi di file
❏ Sintassi: test <espressione> o [ <espressione> ]
❏ Lista di opzioni disponibili con $man test
47
48. Matteo Collica - Shell Scripting (#!/bin/bash) - Test
Confronto tra Interi
-eq: value 1 equals value 2 == (uguale a)
-ge: value 1 greater or equal to value 2 >= (maggiore o uguale a)
-gt: value 1 greater than value 2 > (maggiore di)
-le: value 1 less than or equal to value 2 <= (minore o uguale a)
-lt: value 1 less than value 2 < (minore di)
-ne: value 1 does not equal value 2 != (diverso da)
48
51. Matteo Collica - Shell Scripting (#!/bin/bash) - Test
Test su File
❖ Se un file esiste: -e <FILE>
➢ Se un file esiste ed è una directory: -d
➢ Se un file esiste ed è un file regolare: -f
❖ <FILE1> -nt <FILE2>
➢ Se FILE1 è più recente (come data di modifica) di FILE2
❖ <FILE1> -ot <FILE2>
➢ Se FILE1 è più vecchio di FILE2
51
52. Matteo Collica - Shell Scripting (#!/bin/bash) - Test
Nuova Sintassi
Bash è tra le shell che implementano anche un nuovo comando test,
identificato da doppie parentesi quadre [[, che fornisce funzioni estese
come la verifica se una stringa corrisponde a un’espressione regolare.
Ulteriori informazioni nella pagina di manuale di Bash: $man bash.
52
54. Matteo Collica - Shell Scripting (#!/bin/bash) - Costrutti condizionali
If-Then-fi
If valuta $? (il risultato di un test o lo stato di uscita di un comando)
➔ then: comandi da eseguire se la condizione ritorna “vero”
fi: comando che denota la fine del costrutto if.
54
55. Matteo Collica - Shell Scripting (#!/bin/bash) - Costrutti condizionali
Elif
elif: else if, condizioni aggiuntive, seguite a loro volta da then.
55
56. Matteo Collica - Shell Scripting (#!/bin/bash) - Costrutti condizionali
Else
Comandi che dovranno essere eseguiti nel caso in cui né la condizione
originale (if) né ciascuna di quelle contenute nelle clausole elif siano vere.
56
58. Matteo Collica - Shell Scripting (#!/bin/bash) - Costrutti condizionali
Case
Permette la definizione di più condizioni sul valore di una variabile.
58
59. Matteo Collica - Shell Scripting (#!/bin/bash) - Costrutti condizionali59
Terminando un blocco con ;;
termina anche il costrutto case;
Terminando un blocco con ;&
verrà eseguito anche il blocco
seguente;
Terminando un blocco con ;;&
verrà preso in considerazione
anche il blocco seguente.
Case: 3 modi di Terminare un Blocco
60. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°8
8.
Cicli iterativi
● Cicli for
○ sintassi derivata dal C
● Cicli while
● Cicli until
● Cicli senza condizione
60
61. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi
Cicli For
❏ Itera gli elementi di una lista
❏ Sintassi:
61
for <variabile> in <lista>
do
<istruzioni>
done
<variabile> assume ordinatamente il valore di ogni elemento della lista.
63. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi
Cicli For: Sintassi derivata dal C
Questo ciclo for usa tre diverse espressioni aritmetiche, separate da ;
63
64. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi
Cicli While
❏ Itera finché la condizione è valutata come vera
64
65. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi
Cicli Until
❏ Itera finché la condizione non viene valutata come vera
65
66. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi
Cicli Senza Condizione
Potremmo voler ripetere delle istruzioni senza una condizione specifica
da verificare ad ogni ciclo.
In Bash il simbolo : e la parola true vengono valutati sempre come vero,
perciò se utilizzati come condizione di un ciclo while questa risulterà
sempre verificata, ed eseguirà le istruzioni che contiene all’infinito.
66
67. Matteo Collica - Shell Scripting (#!/bin/bash) - Cicli iterativi67
Produrrebbe lo stesso risultato
68. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°9
9.
Funzioni
● Definire una funzione
● Richiamare una funzione
● Passaggio di parametri
● Valore di ritorno
● Variabili globali
● Variabili locali
68
69. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Funzioni
69
Possiamo immaginare le funzioni in Bash Scripting come degli
script dentro lo script, un insieme di istruzioni che vengono scritte
una sola volta per poi essere richiamate più volte.
70. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Definire una funzione
70
1. 2.
● I due metodi sono validi ed equivalenti, quale utilizzare è solo una questione di preferenza personale;
● In Bash le parentesi () sono solo “per decorazione”, non si metterà mai qualcosa dentro di queste;
● La definizione della funzione (la funzione effettiva stessa) deve apparire nello script prima di qualsiasi chiamata.
71. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Richiamare una funzione
71
72. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Passaggio di parametri
Accade spesso di voler passare alla funzione dei dati da elaborare:
72
73. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Passaggio di parametri
Naturalmente si potrebbero anche passare come parametri gli elementi di un array:
73
74. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Valore di ritorno
74
75. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Scope
Lo scope (ambito) si riferisce a quali
parti di uno script possono
accedere al valore delle variabili.
Variabili
Globali
Scope delle variabili
In Bash, per impostazione
predefinita, le variabili sono definite
come globali (anche se dichiarate
all’interno di una funzione), eccetto
che per i parametri posizionali ($*).
75
77. Matteo Collica - Shell Scripting (#!/bin/bash) - Funzioni
Subshell
In Bash, uno o più comandi racchiusi
da parentesi vengono eseguiti in
una subshell; questa riceve una
copia dell’ambiente di esecuzione,
che include – fra le altre cose – tutte
le variabili dichiarate.
Variabili Locali
Local
La sintassi local <nome>=<valore>
restringe lo scope di una variabile a
ogni diversa chiamata della
funzione in cui viene dichiarata,
rendendola di fatto locale.
77
80. Matteo Collica - Shell Scripting (#!/bin/bash) - Quoting
Weak quoting
Viene anteposto ai caratteri
speciali da non interpretare
come tali.
` (Alt Gr + ‘)
Viene utilizzato per
racchiudere veri e propri
comandi (come per le subshell)
di cui visualizzare l’output
$
Carattere che precede il nome
di una variabile per
visualizzarne il contenuto.
80
“”
81. “
Matteo Collica - Shell Scripting (#!/bin/bash) - Quoting81
Weak (“ ”)
Ad eccezione di tre caratteri
speciali, qualunque altro
carattere racchiuso fra
virgolette doppie non viene
interpretato diversamente.
Politiche di quoting
Strong (‘ ’)
Racchiudendo una sequenza di
caratteri fra apici singoli non
viene interpretato alcun
carattere speciale.
82. Matteo Collica - Shell Scripting (#!/bin/bash) - Quoting
Carattere di escape
82
Un modo alternativo al quoting per far mantenere a Bash i singoli spazi
si ottiene utilizzando il carattere di escape ().
83. Matteo Collica - Shell Scripting (#!/bin/bash) - Lezione n°11
11.
Terminare uno script
● Exit status
● exit
83
84. Matteo Collica - Shell Scripting (#!/bin/bash) - Terminare uno script
Exit Status
Al termine dell’esecuzione di un comando viene ritornato un
valore intero, chiamato exit status, al processo chiamante.
84
85. Matteo Collica - Shell Scripting (#!/bin/bash) - Terminare uno script
Exit Status
Per convenzione, si usa ritornare uno stato di uscita 0 se
l’esecuzione è terminata con successo (che nel caso di un
comando if corrisponde al valore vero), oppure un valore
intero positivo nel caso essa sia fallita con un errore.
85
86. Matteo Collica - Shell Scripting (#!/bin/bash) - Terminare uno script
Exit
Uno script Bash ritorna un valore al processo chiamante
tramite il comando exit <exit status>; che terminerà lo
script e ritornerà uno stato di uscita del valore specificato,
ad indicare o meno un certo tipo di errore.
86
89. Matteo Collica - Shell Scripting (#!/bin/bash) - Debugging
Debugging
Gli strumenti che abbiamo introdotto finora ci permettono di creare
script anche molto complessi, e perciò saremo sempre più esposti a
commettere errori di ogni genere. Il debugging è quindi un’attività molto
importante per ogni programmatore, e inizia dal saper leggere con
attenzione i messaggi di errore (se ne abbiamo ottenuto uno).
89
90. Matteo Collica - Shell Scripting (#!/bin/bash) - Debugging
Modalità di Debugging
Verbose ($bash -v <nome script>)
Ogni comando viene stampato (nel canale
stderr) così come deve essere eseguito,
prima di effettuare ogni singola
espansione.
90
Xtrace ($bash -x <nome script>)
Bash stampa (sempre nel canale stderr)
ogni comando come è stato eseguito dopo
ogni espansione, indicando inoltre il livello
di ogni subshell in cui è stato eseguito (con
il prefisso + per ciascuna di esse).
93. Matteo Collica - Shell Scripting (#!/bin/bash) - Debugging
Debugging step-by-step
Nella creazione di uno script si aggiungono passo passo nuovi
comandi, per cui può essere utile verificarne progressivamente il
funzionamento, per farlo possiamo aiutarci con il comando set.
93
94. Matteo Collica - Shell Scripting (#!/bin/bash) - Debugging
Debugging step-by-step: Set
Il builtin set prevede due opzioni per attivare sia la modalità verbose
che quella xtrace solo per alcune porzioni di codice.
Sintassi
Una volta specificato set -x o set -v ogni comando successivo verrà
eseguito nella modalità specificata finché non si giunge al termine dello
script o ad un comando set +x o set +v.
94
96. Matteo Collica - Shell Scripting (#!/bin/bash) - Debugging
Debugging step-by-step: Echo
L’uso del comando echo per controllare il contenuto di variabili,
posizionato strategicamente all’interno di uno script, è spesso una
soluzione più che valida per individuare eventuali malfunzionamenti.
96
98. Crediti
Un ringraziamento speciale alla disegnatrice che ha
realizzato e rilasciato il template gratuitamente:
★ Template della presentazione scaricato da
SlidesCarnival; disegnato da Jimena Catalina
E ai creatori della guida da cui ho preso maggiormente
ispirazione per la realizzazione di questa presentazione:
★ Shell Scripting e Bash: la Guida
98 Matteo Collica - Shell Scripting (#!/bin/bash) - Crediti