Cómo rastrear la ejecución de comandos en el script de Shell con rastreo de Shell


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

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

  1. Cómo habilitar el modo de depuración de secuencias de comandos de Shell en Linux - Parte 1
  2. Cómo realizar la verificación de sintaxis en el modo de depuración en scripts de Shell - Parte 2

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

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

Usaremos el script de shell sys_info.sh a continuación, que imprime brevemente la fecha y hora de su sistema, el número de usuarios conectados 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 que el script sea ejecutable. El script solo puede ser ejecutado por root, por lo tanto, utilice el comando sudo para ejecutarlo de la siguiente manera:

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

De 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ó por el valor de la variable FECHA.

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

$ sudo bash -n sys_info.sh 

Si miramos críticamente el script de shell, nos daremos cuenta de que a la instrucción if le falta una palabra fi de cierre. Por lo tanto, vamos a agregarlo y la nueva secuencia de comandos debería verse 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 nuevamente e invocalo como root y verifique la sintaxis:

$ sudo bash -n sys_info.sh

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

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

Agregaremos las comillas dobles de cierre en el comando echo y guardaremos el archivo. El guión modificado está 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

Ahora revise sintácticamente el script una vez más.

$ sudo bash -n sys_info.sh

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

$ sudo bash -x sys_info.sh

Ahora ejecute el script.

$ sudo ./sys_info.sh

Importancia del seguimiento de ejecución de scripts de shell

El rastreo de scripts 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 , que está destinado a determinar si un usuario es root o no, ya que el script solo puede ejecutarse 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 instrucción if expresión ["$UID" -ne "$ROOT_ID"] , una vez que no usamos el operador numérico adecuado ( -ne en este caso, que significa no 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 root, 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
}

Nota: Como vimos antes al comienzo de esta serie, el comando integrado set shell puede activar la depuración en una sección particular de un script de shell.

Por lo tanto, la siguiente línea nos ayudará a encontrar este error lógico en la función rastreando 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 la secuencia de comandos, podemos ver que un usuario normal del sistema puede ejecutar la secuencia de comandos sin sudo como se muestra a continuación. 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 abordar cualquier pregunta o comentario sobre esta guía o toda la serie de 3 partes.