Linux Professional Institute Learning Logo.
Torna al contenuto principale
  • Home
    • Tutte le Risorse
    • LPI Learning Materials
    • Collabora
    • Publishing Partner
    • Diventa un Publishing Partner
    • FAQ
    • Collaboratori
    • Contatto
  • LPI.org
3.3 Lezione 2
Argomento 1: La Comunità Linux e una Carriera nell'Open Source
1.1 Evoluzione di Linux e Sistemi Operativi più Diffusi
  • 1.1 Lezione 1
1.2 Principali Applicazioni Open Source
  • 1.2 Lezione 1
1.3 Software e Licenze Open Source
  • 1.3 Lezione 1
1.4 Competenze ICT - Lavorare con Linux
  • 1.4 Lezione 1
Argomento 2: Trovare il Proprio Modo di Operare su un Sistema Linux
2.1 Nozioni di Base sulla Command Line
  • 2.1 Lezione 1
  • 2.1 Lezione 2
2.2 Utilizzo della Command Line per Ottenere Aiuto
  • 2.2 Lezione 1
2.3 Utilizzo di Directory e Elenchi di File
  • 2.3 Lezione 1
  • 2.3 Lezione 2
2.4 Creazione, Spostamento ed Eliminazione di File
  • 2.4 Lezione 1
Argomento 3: Il Potere della Command Line
3.1 Archiviazione dei File sulla Command Line
  • 3.1 Lezione 1
3.2 Ricerca ed Estrazione di Dati dai File
  • 3.2 Lezione 1
  • 3.2 Lezione 2
3.3 Trasformare i Comandi in uno Script
  • 3.3 Lezione 1
  • 3.3 Lezione 2
Argomento 4: Il Sistema Operativo Linux
4.1 Scelta di un Sistema Operativo
  • 4.1 Lezione 1
4.2 Comprendere l'Hardware del Computer
  • 4.2 Lezione 1
4.3 Dove Sono Memorizzati i Dati
  • 4.3 Lezione 1
  • 4.3 Lezione 2
4.4 Il Tuo Computer in Rete
  • 4.4 Lezione 1
Argomento 5: Sicurezza e Permessi sui File
5.1 Sicurezza di Base e Identificazione dei Tipi di Utente
  • 5.1 Lezione 1
5.2 Creazione di Utenti e Gruppi
  • 5.2 Lezione 1
5.3 Gestione delle Autorizzazioni e delle Proprietà dei File
  • 5.3 Lezione 1
5.4 Directory e File Speciali
  • 5.4 Lezione 1
How to get certified
  1. Argomento 3: Il Potere della Command Line
  2. 3.3 Trasformare i Comandi in uno Script
  3. 3.3 Lezione 2

3.3 Lezione 2

Certificazione:

Linux Essentials

Versione:

1.6

Argomento:

3 Il Potere della Command Line

Obiettivo:

3.3 Trasformare i Comandi in uno Script

Lezione:

2 di 2

Introduzione

Nell’ultima lezione abbiamo utilizzato questo semplice esempio per mostrare uno script Bash:

#!/bin/bash

# A simple script to greet a single user.

if [ $# -eq 1 ]
then
  username=$1

  echo "Hello $username!"
else
  echo "Please enter only one argument."
fi
echo "Number of arguments: $#."
  • Tutti gli script dovrebbero iniziare con uno shebang che definisce il percorso dell’interprete.

  • Tutti gli script dovrebbero includere dei commenti per descrivere il loro utilizzo.

  • Questo specifico script funziona con un argomento che gli viene passato al momento della sua invocazione.

  • Questo script contiene una istruzione if che testa le condizioni della variabile interna (built-in) $# che contiene il numero di argomenti.

  • Se il numero di argomenti passati allo script è uguale a 1, allora il valore del primo argomento viene assegnato a una nuova variabile chiamata username e lo script stampa un saluto all’utente. In caso contrario, viene visualizzato un messaggio di errore.

  • Infine, lo script stampa il numero di argomenti. Questo è utile per il debug.

Questo è un esempio utile per iniziare a spiegare alcune delle altre caratteristiche degli script Bash.

Codici di Uscita

Avrai notato che il nostro script ha due possibili stati: o stampa "Hello <user>!" o stampa un messaggio di errore. Questo è piuttosto normale per molte delle nostre principali utility. Considera cat, con cui senza dubbio stai diventando molto familiare.

Confrontiamo ora una situazione in cui cat viene eseguito con successo con una in cui dà errore. Ricorda che il nostro esempio sopra riportato è uno script chiamato new_script.sh.

$ cat -n new_script.sh

     1	#!/bin/bash
     2
     3	# A simple script to greet a single user.
     4
     5	if [ $# -eq 1 ]
     6	then
     7	  username=$1
     8
     9	  echo "Hello $username!"
    10	else
    11	  echo "Please enter only one argument."
    12	fi
    13	echo "Number of arguments: $#."

Questo comando viene eseguito con successo; nota che l’opzione -n ha anche stampato i numeri di riga. Questi sono molto utili durante il debug degli script, ma tieni presente che non fanno parte dello script.

Controlliamo ora il valore di una nuova variabile interna (built-in): $?. Per il momento, nota solamente il valore di output:

$ echo $?
0

Consideriamo ora una situazione in cui cat non viene eseguito con successo. Per prima cosa osserviamo il messaggio di errore e poi controlliamo il valore di $?.

$ cat -n dummyfile.sh
cat: dummyfile.sh: No such file or directory
$ echo $?
1

La spiegazione per questo comportamento è la seguente: qualsiasi esecuzione dell’utility cat restituisce un codice di uscita. Un codice di uscita indica se il comando è stato eseguito con successo o se si è verificato un errore. Un codice di uscita pari a zero indica che il comando è stato completato correttamente. Questo è vero per quasi tutti i comandi Linux con cui hai a che fare. Qualsiasi altro codice di uscita indica un errore di qualche tipo. Il codice di uscita dell'ultimo comando eseguito è memorizzato nella variabile $?.

I codici di uscita, di solito, non sono controllati dagli utenti in carne e ossa, ma sono molto utili durante la redazione di script. Considera uno script che copia i file su un’unità di rete remota: esistono molte cause per le quali l’attività di copia potrebbe non andare a buon fine: per esempio, la nostra macchina locale potrebbe non essere collegata alla rete o l’unità remota potrebbe essere piena. Controllando il codice di uscita della nostra utility di copia possiamo avvisare l’utente di eventuali problemi durante l’esecuzione dello script.

È buona norma implementare i codici di uscita ed è ciò che faremo ora. Abbiamo due percorsi nel nostro script: un successo e un errore. Usiamo zero per indicare il successo e uno per indicare l’errore.

     1	#!/bin/bash
     2
     3	# A simple script to greet a single user.
     4
     5	if [ $# -eq 1 ]
     6	then
     7	  username=$1
     8
     9	  echo "Hello $username!"
    10	  exit 0
    11	else
    12	  echo "Please enter only one argument."
    13	  exit 1
    14	fi
    15	echo "Number of arguments: $#."
$ ./new_script.sh Carol
Hello Carol!
$ echo $?
0

Nota che il comando echo alla riga 15 viene completamente ignorato. Infatti, exit termina immediatamente lo script; quindi questa riga non viene mai raggiunta.

Gestire più Argomenti

Per ora il nostro script può gestire un solo nome utente alla volta. Qualsiasi numero di argomenti diverso da 1 causerà un errore. Esaminiamo come poter rendere questo script più versatile.

Il primo istinto di un utente potrebbe essere quello di utilizzare più variabili posizionali come, per esempio, $2, $3 e così via. Sfortunatamente, non possiamo prevedere il numero di argomenti che un utente potrebbe voler utilizzare. Per risolvere questo problema può essere utile introdurre altre variabili interne (built-in).

Modifichiamo la logica del nostro script: in caso ci siano 0 argomenti, dovrebbe essere generato un errore, ma un qualsiasi altro numero di argomenti renderebbe lo script corretto. Questo nuovo script si chiamerà friendly2.sh.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  echo "Hello $@!"
    11	  exit 0
    12	fi
$ ./friendly2.sh Carol Dave Henry
Hello Carol Dave Henry!

Esistono due variabili interne (built-in) che contengono tutti gli argomenti passati allo script: $@ e $*. Nella maggior parte dei casi entrambe si comportano allo stesso modo. Bash analizza gli argomenti e li separa quando incontra uno spazio. In pratica, il contenuto di $@ ha questo aspetto:

0

1

2

Carol

Dave

Henry

Se hai familiarità con altri linguaggi di programmazione potresti conoscere questo tipo di variabile come un array. Gli array in Bash possono essere creati semplicemente inserendo uno spazio tra gli elementi, come per la variabile FILES nello script arraytest qui sotto:

FILES="/usr/sbin/accept /usr/sbin/pwck/ usr/sbin/chroot"

La variabile contiene un elenco di diversi elementi. Per ora non è molto utile, poichè non abbiamo ancora introdotto un modo per gestire singolarmente questi elementi.

Cicli For

Facciamo riferimento all’esempio arraytest mostrato in precedenza. Se ricordi, in questo esempio abbiamo specificato un nostro array chiamato FILES. Ciò di cui abbiamo bisogno è un modo per “spacchettare” questa variabile e accedere a ogni singolo valore, uno dopo l’altro. Per fare questo, useremo una struttura chiamata ciclo for, che è presente in tutti i linguaggi di programmazione. Faremo riferimento a due variabili: una è l’intervallo e l’altra è il valore individuale su cui stiamo attualmente lavorando. Questo è lo script nella sua interezza:

#!/bin/bash

FILES="/usr/sbin/accept /usr/sbin/pwck/ usr/sbin/chroot"

for file in $FILES
do
  ls -lh $file
done
$ ./arraytest
lrwxrwxrwx 1 root root 10 Apr 24 11:02 /usr/sbin/accept -> cupsaccept
-rwxr-xr-x 1 root root 54K Mar 22 14:32 /usr/sbin/pwck
-rwxr-xr-x 1 root root 43K Jan 14 07:17 /usr/sbin/chroot

Se fai nuovamente riferimento all’esempio friendly2.sh sopra riportato noterai che stiamo lavorando con una serie di valori contenuti all’interno di un’unica variabile $@. Per maggiore chiarezza chiameremo quest’ultima variabile username. Il nostro script ora ha questo aspetto:

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  for username in $@
    11	  do
    12	    echo "Hello $username!"
    13	  done
    14	  exit 0
    15	fi

Ricorda che la variabile che definisci può avere un qualunque nome e che tutte le righe all’interno di do…​ done verranno eseguite una volta per ogni elemento dell’array. Osserviamo l’output del nostro script:

$ ./friendly2.sh Carol Dave Henry
Hello Carol!
Hello Dave!
Hello Henry!

Supponiamo ora di voler rendere il nostro output un po' più umano, facendo in modo che il saluto appaia su un’unica riga.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  echo -n "Hello $1"
    11	  shift
    12	  for username in $@
    13	  do
    14	    echo -n ", and $username"
    15	  done
    16	  echo "!"
    17	  exit 0
    18	fi

Un paio di note:

  • L’uso di -n con echo elimina il carattere di nuova riga dopo la stampa. Questo significa che tutto l’output verrà stampato sulla stessa riga e il carattere di nuova riga verrà stampato solo dopo il ! della riga 16.

  • Il comando shift rimuove il primo elemento del nostro array, in modo tale che questo:

0

1

2

Carol

Dave

Henry

diventi questo:

0

1

Dave

Henry

Diamo un’occhiata all’output:

$ ./friendly2.sh Carol
Hello Carol!
$ ./friendly2.sh Carol Dave Henry
Hello Carol, and Dave, and Henry!

Usare le Espressioni Regolari per Eseguire il Controllo degli Errori

Potremmo voler verificare tutti gli argomenti che inserisce l’utente. Per esempio, potremmo verificare che tutti i nomi passati a friendly2.sh contengano solo lettere, in modo tale che qualsiasi carattere speciale o numero causi un errore. Per eseguire questo controllo degli errori useremo grep.

Ricorda che possiamo usare le espressioni regolari con grep.

$ echo Animal | grep "^[A-Za-z]*$"
Animal
$ echo $?
0
$ echo 4n1ml | grep "^[A-Za-z]*$"
$ echo $?
1

^ e $ indicano rispettivamente l’inizio e la fine della riga. [A-Za-z] indica un intervallo di lettere, maiuscole o minuscole. * è un quantificatore che modifica il nostro intervallo di lettere in modo che si abbia corrispondenza per 0 o un qualsiasi numero di lettere. In sintesi: il nostro grep verrà eseguito con successo se l’input è costituito solo da lettere, e darà errore in caso contrario.

La prossima cosa da notare è che grep restituisce i codici di uscita in base al fatto che ci sia o meno corrispondenza con quanto inserito. Se c’è corrispondenza restituisce 0, mentre se non c’è corrispondenza restituisce 1. Possiamo quindi utilizzarlo per testare gli argomenti all’interno del nostro script.

     1	#!/bin/bash
     2
     3	# a friendly script to greet users
     4
     5	if [ $# -eq 0 ]
     6	then
     7	  echo "Please enter at least one user to greet."
     8	  exit 1
     9	else
    10	  for username in $@
    11	  do
    12	    echo $username | grep "^[A-Za-z]*$" > /dev/null
    13	    if [ $? -eq 1 ]
    14	    then
    15	      echo "ERROR: Names must only contains letters."
    16	      exit 2
    17	    else
    18	      echo "Hello $username!"
    19	    fi
    20	  done
    21	  exit 0
    22	fi

Nella riga 12 redirigiamo lo standard output verso /dev/null, il che rappresenta un semplice modo per sopprimere tale output. Non vogliamo vedere alcun output del comando grep: vogliamo solo testare il suo codice di uscita, cosa che facciamo nella riga 13. Nota inoltre che stiamo usando un codice di uscita pari a 2 per indicare un argomento non valido. In genere è buona norma utilizzare codici di uscita diversi per indicare errori diversi: in questo modo, un utente esperto può utilizzare questi codici di uscita per individuare e risolvere i problemi.

$ ./friendly2.sh Carol Dave Henry
Hello Carol!
Hello Dave!
Hello Henry!
$ ./friendly2.sh 42 Carol Dave Henry
ERROR: Names must only contains letters.
$ echo $?
2

Esercizi Guidati

  1. Osserva il contenuto di script1.sh qui sotto riportato:

    #!/bin/bash
    
    if [ $# -lt 1 ]
    then
      echo "This script requires at least 1 argument."
      exit 1
    fi
    
    echo $1 | grep "^[A-Z]*$" > /dev/null
    if [ $? -ne 0 ]
    then
      echo "no cake for you!"
      exit 2
    fi
    
    echo "here's your cake!"
    exit 0

    Quale sarà l’output dei seguenti comandi?

    • ./script1.sh

    • echo $?

    • ./script1.sh cake

    • echo $?

    • ./script1.sh CAKE

    • echo $?

  2. Osserva il contenuto del file script2.sh:

    for filename in $1/*.txt
    do
       cp $filename $filename.bak
    done

    Descrivi lo scopo di questo script.

Esercizi Esplorativi

  1. Crea uno script che accetti un numero qualsiasi di argomenti dall’utente e stampi solamente gli argomenti che hanno come valore un numero maggiore di 10.

Sommario

In questa lezione hai imparato:

  • Cosa sono i codici di uscita, cosa significano e come si implementano;

  • Come controllare il codice di uscita di un comando;

  • Cosa sono i cicli for e come usarli con gli array;

  • Come usare grep, le espressioni regolari e i codici di uscita per controllare l’input dell’utente negli script.

Comandi utilizzati negli esercizi:

shift

Rimuove il primo elemento di un array.

Variabili speciali:

$?

Contiene il codice di uscita dell’ultimo comando eseguito.

$@, $*

Contiene tutti gli argomenti passati allo script, sotto forma di un array.

Risposte agli Esercizi Guidati

  1. Osserva il contenuto di script1.sh qui sotto riportato:

    #!/bin/bash
    
    if [ $# -lt 1 ]
    then
      echo "This script requires at least 1 argument."
      exit 1
    fi
    
    echo $1 | grep "^[A-Z]*$" > /dev/null
    if [ $? -ne 0 ]
    then
      echo "no cake for you!"
      exit 2
    fi
    
    echo "here's your cake!"
    exit 0

    Quale sarà l’output dei seguenti comandi?

    • Comando: ./script1.sh

      Output: This script requires at least 1 argument.

    • Comando: echo $?

      Output: 1

    • Comando: ./script1.sh cake

      Output: no cake for you!

    • Comando: echo $?

      Output: 2

    • Comando: ./script1.sh CAKE

      Output: here’s your cake!

    • Comando: echo $?

      Output: 0

  2. Osserva il contenuto del file script2.sh:

    for filename in $1/*.txt
    do
       cp $filename $filename.bak
    done

    Descrivi lo scopo di questo script.

    Questo script crea delle copie di backup di tutti i file che terminano con .txt che si trovano in una sottodirectory definita nel primo argomento.

Risposte agli Esercizi Esplorativi

  1. Crea uno script che accetti un numero qualsiasi di argomenti dall’utente e stampi solamente gli argomenti che hanno come valore un numero maggiore di 10.

    #!/bin/bash
    
    for i in $@
    do
      echo $i | grep "^[0-9]*$" > /dev/null
      if [ $? -eq 0 ]
      then
        if [ $i -gt 10 ]
        then
          echo -n "$i "
        fi
      fi
    done
    echo ""

Linux Professional Institute Inc. Tutti i diritti riservati. Visita il sito Learning Materials: https://learning.lpi.org
Quest'opera è sotto la licenza 'Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License'.

Prossima Lezione

4.1 Scelta di un Sistema Operativo (4.1 Lezione 1)

Leggi la prossima Lezione

Linux Professional Institute Inc. Tutti i diritti riservati. Visita il sito Learning Materials: https://learning.lpi.org
Quest'opera è sotto la licenza 'Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License'.

LPI è una organizzazione non-profit.

© 2023 Linux Professional Institute (LPI) è lo standard di certificazione globale e l'organizzazione di supporto alla carriera per i Professionisti Open Source. Con più di 200,000 titolari di Certificazione, è il primo e il più grande ente di Certificazione Open Source e Linux vendor-neutral. LPI ha professionisti certificati in oltre 180 Paesi, offre i suoi Esami in più lingue e ha centinaia di Partner di formazione in tutto il mondo.

La nostra missione è promuovere l'uso dell'Open Source supportando le persone che vi lavorano.

  • LinkedIn
  • flogo-RGB-HEX-Blk-58 Facebook
  • Twitter
  • Contattaci
  • Privacy & Cookie Policy

Trovato un errore? Per favore scrivi a contattaci.

© 1999–2023 The Linux Professional Institute Inc. Tutti i diritti riservati.