Com rastrejar l'execució d'ordres a l'script de Shell amb Shell Tracing


En aquest article de la sèrie de depuració d'scripts d'intèrpret d'ordres, explicarem el tercer mode de depuració d'scripts d'intèrpret d'ordres, és a dir, el seguiment de l'intèrpret d'ordres i veurem alguns exemples per demostrar com funciona i com es pot utilitzar.

La part anterior d'aquesta sèrie il·lumina clarament els altres dos modes de depuració d'scripts d'intèrpret d'ordres: el mode detallat i el mode de comprovació de sintaxi amb exemples fàcils d'entendre de com habilitar la depuració d'scripts d'intèrpret d'ordres en aquests modes.

  1. Com habilitar el mode de depuració d'scripts de Shell a Linux - Part 1
  2. Com dur a terme el mode de depuració de comprovació de sintaxi als scripts de Shell - Part 2

El seguiment de l'intèrpret d'ordres simplement significa el seguiment de l'execució de les ordres en un script d'intèrpret d'ordres. Per activar el seguiment de l'intèrpret d'ordres, utilitzeu l'opció de depuració -x.

Això dirigeix l'intèrpret d'ordres perquè mostri totes les ordres i els seus arguments al terminal mentre s'executen.

Utilitzarem l'script d'intèrpret d'ordres sys_info.sh a continuació, que imprimeix breument la data i l'hora del vostre sistema, el nombre d'usuaris que han iniciat sessió i el temps de funcionament del sistema. Tanmateix, conté errors de sintaxi que hem de trobar i corregir.

#!/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

Deseu el fitxer i feu que l'script sigui executable. L'script només es pot executar per root, per tant, utilitzeu l'ordre sudo per executar-lo de la següent manera:

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

A partir de la sortida anterior, podem observar que una ordre s'executa primer abans que la seva sortida es substitueixi com el valor d'una variable.

Per exemple, la data es va executar per primera vegada i la seva sortida es va substituir com el valor de la variable DATE.

Podem realitzar una comprovació de sintaxi per mostrar només els errors de sintaxi de la següent manera:

$ sudo bash -n sys_info.sh 

Si mirem críticament l'script de l'intèrpret d'ordres, ens adonarem que a la instrucció if li falta una paraula fi de tancament. Per tant, afegim-lo i el nou script ara hauria de semblar a continuació:

#!/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

Deseu el fitxer de nou i invoqueu-lo com a root i feu una mica de comprovació de sintaxi:

$ sudo bash -n sys_info.sh

El resultat de la nostra operació de comprovació de sintaxi anterior encara mostra que hi ha un error més en el nostre script a la línia 21. Per tant, encara tenim una mica de correcció de sintaxi per fer.

Si mirem l'script analíticament una vegada més, l'error a la línia 21 es deu a que falta una cometa doble de tancament (”) a l'última ordre d'eco dins de la funció print_sys_info .

Afegirem les cometes dobles de tancament a l'ordre echo i desarem el fitxer. L'script canviat és el següent:

#!/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

Ara comproveu sintàcticament l'script una vegada més.

$ sudo bash -n sys_info.sh

L'ordre anterior no produirà cap sortida perquè el nostre script ara és sintàcticament correcte. També podem rastrejar l'execució de l'script per segona vegada i hauria de funcionar bé:

$ sudo bash -x sys_info.sh

Ara executeu l'script.

$ sudo ./sys_info.sh

Importància del seguiment de l'execució de l'script de Shell

El seguiment de l'script de Shell ens ajuda a identificar els errors de sintaxi i, el que és més important, els errors lògics. Preneu, per exemple, la funció check_root a l'script de l'intèrpret d'ordres sys_info.sh, que pretén determinar si un usuari és root o no, ja que l'script només es pot executar. pel superusuari.

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

La màgia aquí està controlada per l'expressió if expressió [ \$UID\ -ne \$ROOT_ID\ ], un cop no utilitzem l'operador numèric adequat (-ne en aquest cas, que vol dir no igual ), acabem amb un possible error lògic.

Suposant que hem utilitzat -eq (significa igual a), això permetria que qualsevol usuari del sistema així com l'usuari root executessin l'script, per tant, un error lògic.

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

Nota: tal com vam veure abans al començament d'aquesta sèrie, l'ordre incorporada set shell pot activar la depuració en una secció concreta d'un script de shell.

Per tant, la línia següent ens ajudarà a trobar aquest error lògic a la funció rastrejant la seva execució:

L'script amb un error lògic:

#!/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

Deseu el fitxer i invoqueu l'script, podem veure que un usuari normal del sistema pot executar l'script sense sudo com a la sortida següent. Això es deu al fet que el valor de USER_ID és 100, que no és igual a l'arrel ROOT_ID que és 0.

$ ./sys_info.sh

Bé, això és tot de moment, hem arribat al final de la sèrie de depuració de scripts d'intèrpret d'ordres, el formulari de resposta següent es pot utilitzar per respondre qualsevol pregunta o comentari sobre aquesta guia o tota la sèrie de 3 parts.