Cómo rastrear la ejecución de comandos en un script de shell con un seguimiento de shell


En este artículo de la serie de depuración de script de shell, explicaremos el tercer modo de depuración de script de shell, que es el rastreo de shell, y veremos algunos ejemplos para demostrar cómo funciona y cómo se puede usar.

La parte anterior de esta serie claramente arroja luz sobre los otros dos modos de depuración del script de shell: modo detallado y comprobación de sintaxis con ejemplos fáciles de entender de cómo habilitar el shell Depuración de scripts en estos modos.

  1. How To Enable Shell Script Debugging Mode in Linux – Part 1
  2. How to Perform Syntax Checking Debugging Mode in Shell Scripts – Part 2

El seguimiento de shell simplemente significa el seguimiento de la ejecución de los comandos en un script de shell. Para activar el seguimiento de shell, use la opción de depuración -x .

Esto dirige al shell a mostrar todos los comandos y sus argumentos en el terminal a medida que se ejecutan.

Usaremos la secuencia de comandos de shell sys_info.sh a continuación, que imprime brevemente la fecha y la hora del sistema, la cantidad de usuarios registrados y el tiempo de actividad del sistema. Sin embargo, contiene errores de sintaxis que debemos encontrar y 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

Guarde el archivo y haga el script ejecutable. El script solo puede ejecutarse por root, por lo tanto, emplee el comando sudo para ejecutarlo de la siguiente manera:

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

Desde la salida anterior, podemos observar que, primero se ejecuta un comando antes de que su salida se sustituya como el valor de una variable.

Por ejemplo, la fecha se ejecutó por primera vez y su salida se sustituyó como el valor de la variable FECHA .

Podemos realizar una comprobación de sintaxis para mostrar solo los errores de sintaxis de la siguiente manera:

$ sudo bash -n sys_info.sh 

Si observamos críticamente el script de shell, nos daremos cuenta de que a if statement le falta una palabra de cierre de fi . Por lo tanto, agreguémoslo y el nuevo script debería verse como a continuación:

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

Guarde el archivo de nuevo, invóquelo como root y realice algunas comprobaciones de sintaxis:

$ sudo bash -n sys_info.sh

El resultado de nuestra operación de comprobación de sintaxis anterior todavía muestra que hay un error más en nuestro script en línea 21 . Por lo tanto, todavía tenemos que hacer una corrección de sintaxis.

Si observamos el guión analíticamente una vez más, el error en línea 21 se debe a que falta una comilla de cierre (”) en el último comando echo dentro del print_sys_info función.

Agregaremos la comilla doble de cierre en el comando echo y guardaremos el archivo. El script cambiado está abajo:

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

Ahora compruebe sintácticamente el guión una vez más.

$ sudo bash -n sys_info.sh

El comando anterior no producirá ningún resultado porque nuestra secuencia de comandos ahora es sintácticamente correcta. También podemos rastrear la ejecución del script todo por segunda vez y debería funcionar bien:

$ sudo bash -x sys_info.sh

Ahora ejecuta el script.

$ sudo ./sys_info.sh

Importancia del seguimiento de ejecución de shell script

El rastreo del script de Shell nos ayuda a identificar errores de sintaxis y, lo que es más importante, errores lógicos. Tomemos, por ejemplo, la función check_root en el script de shell sys_info.sh , cuyo objetivo es determinar si un usuario es root o no, ya que solo se puede ejecutar el script por el superusuario.

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

La magia aquí está controlada por la expresión if declaración [1000 -ne] , una vez que no usamos el operador numérico adecuado ( -ne en este caso, que significa que no es igual), terminamos con un posible error lógico.

Suponiendo que usamos -eq (significa igual a), esto permitiría a cualquier usuario del sistema así como al usuario raíz ejecutar el script, por lo tanto, un error lógico.

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

rojo

Por lo tanto, la línea a continuación nos ayudará a encontrar este error lógico en la función al rastrear su ejecución:

El script con un error lógico:

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

Guarde el archivo e invoque el script, podemos ver que un usuario normal del sistema puede ejecutar el script sin sudo como se muestra en la siguiente salida. Esto se debe a que el valor de USER_ID es 100 que no es igual a la raíz ROOT_ID que es 0 .

$ ./sys_info.sh

Bueno, eso es todo por ahora, hemos llegado al final de la serie de depuración de scripts de shell, el formulario de respuesta a continuación se puede utilizar para dirigirnos cualquier pregunta o comentario sobre esta guía o la serie completa de 3 partes.