Cómo rastrear la ejecución de comandos en Shell Script con Shell Tracing
En este artículo de la serie de depuración de scripts de shell, explicaremos el tercer modo de depuración de scripts 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 claramente sobre los otros dos modos de depuración de scripts de Shell: modo detallado y modo de comprobación de sintaxis con ejemplos fáciles de entender de cómo habilitar Shell. depuración de scripts en estos modos.
- Cómo habilitar el modo de depuración de scripts de Shell en Linux – Parte 1
- Cómo realizar la verificación de sintaxis en el modo de depuración en scripts de Shell – Parte 2
El seguimiento de Shell simplemente significa rastrear la ejecución de los comandos en un script de Shell. Para activar el seguimiento de shell, utilice la opción de depuración -x
.
Esto indica al shell que muestre todos los comandos y sus argumentos en la 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, la cantidad 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 sólo puede ser ejecutado por root, por lo tanto, utilice el comando sudo para ejecutarlo como se muestra a continuación:
chmod +x sys_info.sh
sudo bash -x sys_info.sh
Del resultado 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ó primero y su salida se sustituyó como el valor de la variable DATE.
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 observamos 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, agreguémoslo y el nuevo script debería lucir como se muestra 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, invoquelo como root y realice algunas comprobaciones de sintaxis:
sudo bash -n sys_info.sh
El resultado de nuestra operación de verificación de sintaxis anterior aún muestra que hay un error más en nuestro script en la línea 21. Entonces, todavía tenemos algunas correcciones de sintaxis por hacer.
Si revisamos el script analíticamente una vez más, el error en la línea 21 se debe a que falta una comilla doble de cierre ( ”)
en el último comando de eco dentro del función print_sys_info
.
Agregaremos la comilla doble de cierre en el comando echo y guardaremos el archivo. El script 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 revisa 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 la ejecución del script de Shell
El seguimiento 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 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 expresión if Statement
[ "$UID" -ne "$ROOT_ID" ]
, una vez que no utilizamos 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, de ahí 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 el script. Podemos ver que un usuario normal del sistema puede ejecutar el script 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 del script de shell; el formulario de respuesta a continuación se puede utilizar para enviarnos cualquier pregunta o comentario sobre esta guía o la serie completa de 3 partes.