Ricerca nel sito web

Come tracciare l'esecuzione dei comandi nello script di shell con Shell Tracing


In questo articolo della serie sul debug degli script di shell, spiegheremo la terza modalità di debug degli script di shell, ovvero il tracciamento della shell, e vedremo alcuni esempi per dimostrare come funziona e come può essere utilizzata.

La parte precedente di questa serie fa chiaramente luce sulle altre due modalità di debug degli script della shell: la modalità verbose e la modalità controllo della sintassi con esempi di facile comprensione su come abilitare la shell debug degli script in queste modalità.

  1. Come abilitare la modalità di debug degli script di Shell in Linux - Parte 1
  2. Come eseguire la modalità di debug del controllo della sintassi negli script di shell - Parte 2

Tracciare la shell significa semplicemente tracciare l'esecuzione dei comandi in uno script di shell. Per attivare il tracciamento della shell, utilizzare l'opzione di debug -x.

Questo ordina alla shell di visualizzare tutti i comandi e i relativi argomenti sul terminale mentre vengono eseguiti.

Utilizzeremo lo script di shell sys_info.sh riportato di seguito, che stampa brevemente la data e l'ora del sistema, il numero di utenti che hanno effettuato l'accesso e il tempo di attività del sistema. Tuttavia, contiene errori di sintassi che dobbiamo trovare e correggere.

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

Salvare il file e rendere eseguibile lo script. Lo script può essere eseguito solo da root, quindi utilizza il comando sudo per eseguirlo come di seguito:

chmod +x sys_info.sh
sudo bash -x sys_info.sh

Dall'output sopra, possiamo osservare che un comando viene eseguito prima che il suo output venga sostituito come valore di una variabile.

Ad esempio, la data è stata eseguita per la prima volta e il suo output è stato sostituito con il valore della variabile DATE.

Possiamo eseguire il controllo della sintassi per visualizzare solo gli errori di sintassi come segue:

sudo bash -n sys_info.sh 

Se osserviamo criticamente lo script della shell, ci renderemo conto che all'istruzione if manca una parola fi di chiusura. Pertanto, aggiungiamolo e il nuovo script ora dovrebbe apparire come di seguito:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
   fi    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

Salva nuovamente il file e invocalo come root ed esegui un controllo della sintassi:

sudo bash -n sys_info.sh

Il risultato della nostra operazione di controllo della sintassi sopra mostra ancora che c'è un altro bug nel nostro script alla riga 21. Quindi, abbiamo ancora qualche correzione di sintassi da fare.

Se esaminiamo lo script in modo analitico ancora una volta, l'errore sulla riga 21 è dovuto alla mancanza di una virgoletta doppia di chiusura ( ”) nell'ultimo comando echo all'interno del print_sys_info funzione.

Aggiungeremo le virgolette doppie di chiusura nel comando echo e salveremo il file. Lo script modificato è il seguente:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

check_root
print_sys_info

exit 0

Ora controlla sintatticamente lo script ancora una volta.

sudo bash -n sys_info.sh

Il comando sopra non produrrà alcun output perché il nostro script ora è sintatticamente corretto. Possiamo anche tracciare l'esecuzione dello script una seconda volta e dovrebbe funzionare bene:

sudo bash -x sys_info.sh

Ora esegui lo script.

sudo ./sys_info.sh

Importanza del tracciamento dell'esecuzione degli script di shell

Il tracciamento degli script della shell ci aiuta a identificare gli errori di sintassi e, soprattutto, gli errori logici. Prendiamo ad esempio la funzione check_root nello script di shell sys_info.sh, che ha lo scopo di determinare se un utente è root o meno, poiché allo script è consentita solo l'esecuzione dal superutente.

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

La magia qui è controllata dall'espressione if espressione [ "$UID" -ne "$ROOT_ID" ], una volta che non utilizziamo l'operatore numerico adatto ( -ne in questo caso, che significa not equal ), ci ritroveremo con un possibile errore logico.

Supponendo di aver utilizzato -eq ( significa uguale a), ciò consentirebbe a qualsiasi utente di sistema, nonché all'utente root, di eseguire lo script, quindi un errore logico.

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

Nota: come abbiamo visto all'inizio di questa serie, il comando integrato set shell può attivare il debug in una particolare sezione di uno script di shell.

Pertanto, la riga seguente ci aiuterà a trovare questo errore logico nella funzione tracciandone l'esecuzione:

Lo script con un errore logico:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

#turning on and off debugging of check_root function
set -x ; check_root;  set +x ;
print_sys_info

exit 0

Salva il file e invoca lo script, possiamo vedere che un normale utente del sistema può eseguire lo script senza sudo come nell'output seguente. Questo perché il valore di USER_ID è 100 che non è uguale al ROOT_ID root che è 0.

./sys_info.sh

Bene, per ora è tutto, siamo arrivati alla fine della serie di debug degli script di shell, il modulo di risposta sottostante può essere utilizzato per indirizzarci qualsiasi domanda o feedback, riguardante questa guida o l'intera serie in 3 parti.