educación, informática y demás

GNU/Linux bash, Shell scripts

Bash Shell Scripting: Recomendaciones y errores

Errores típicos

Primera línea del script

Es importante que la primera línea del script especifique la ruta del interprete de comandos que se utilizará para ejecutarlo. Para ello se debe seguir la siguiente sintásis.

Debe aparecer un comentario, cuyo primer caracter pegado al caracter # sea un signo de admiración de cierre, seguido por la ruta del interprete de comandos.

Si esto no es así, la shell puede utilizar otro interprete de comandos, como sh, que no tenga las mismas herramientas que /bin/bash.

Error: [ ] – Comando test

Test es un comando que sirve para comparar cadenas de caracteres, números enteros y datos sobre ficheros.

Cuando usamos el comando test en un if para comprobar una condición podemos escribir test o bien escribir la expresión a comprobar entre corchetes: [ expresion ].

En la línea 5, el comando que vamos a ejecutar para realizar la comprobación del if es: test ! id $usuario. Estamos ejecutando el comando test!!!!

El comando if de la línea 13 si que comprueba si el usuario existe en el sistema.

Asignación de variables con $

Cuando asignamos un valor a una variable, en la parte izquierda de la asignación escribimos el nombre de la variable, después sin espacios el signo igual y por último el valor que queremos asignar a dicha variable.

A veces, con las prisas, podemos escribir algo parecido a lo siguiente:

Esto fallará, puesto que en la parte izquierda de la asignación hemos escrito el nombre de la variable con un carácter dolar delante.

La forma correcta de hacerlo sería así:

Lo mismo nos puede pasar con un bucle for o con un comando read

La forma correcta sería la siguiente:

Control de errores

A continuación vamos a utilizar el comando if para realizar comprobaciones típicas en control de errores de script

¿Qué son los controles de errores?. A ver, la expresión seguro que no me la he inventado yo, pero la he puesto casi instintivamente en uso en los scripts por que yo la he utilizado mucho en programación.

El control de errores se podría definir como la parte del programa que se encarga de evitar errores en nuestro script en tiempo de ejecución.

No podemos evitar todos los errores que se puedan dar en el momento de ejecutar el script. Sin embargo, si que podemos evitar muchas situaciones de error que se pueden causar al ejecutar un script,.

Por ejemplo, si nuestro script necesita que se proporcione el nombre de un usuario por parámetro. podemos comprobar que el usuario ha proporcionado algún valor por parámetro. Si además, queremos ser más técnicos o más detallistas, podemos comprobar que el nombre de usuario que se ha proporcionado existe en el sistema.

Al final, cuando termine el control de errores, los comandos dedicadas a ello, estaremos seguros de que se cumplen los requisitos o condiciones mínimas para que se ejecute nuestro script.

Función error

Cuando no se cumple alguno de los requisitos de nuestro script y lo detectamos en el proceso de control de errores, deberíamos terminar la ejecución del script mostrando un mensaje de error adecuado, que informe al usuario del error producido para que pueda solucionarlo, y devolviendo un código de salida de error, es decir un valor distinto de cero.

Como esta situación se puede repetir varias veces en nuestro script, estaría bien contar con una función que se encargue de todo el proceso. Podemos utilizar la siguiente función error:

El script necesita un valor por parámetro

Nuestro script necesta obtener un valor por parámetro. Por ejemplo, el nombre de un usuario.

Si sabemos que es un usuario, lo primero que hacemos es asignar el valor del primer parámetro a una variable que tenga un nombre significativo. Después realizamos la comprobación.

Comprobamos si la variable que contiene el valor pasado en el primer parámetro está vacía.

Podríamos haber comprobado primero directamente el valor de $1

Las dos son iguales, sin embargo la primera opción es más comprensible para un humano, es más fácil para razonar.

Hay más formas de comprobarlo. Podemos utilizar la variable $# para comprobar que me han pasado un parámetro.

También podríamos haber comprobado si el número de parámetros es cero. En ese caso, no me han pasado nada…

El script necesita dos parámetros

Por ejemplo, un script que necesite que se pase el nombre de un usuario y la ruta de su directorio personal. Si no se pasan los dos parámetros el script se deberá mostrar un mensaje de error adecuado y terminar la ejecución del script con un código de salida de error.

También podríamos haber comprobado cada uno de los parámetros. En este caso son solo dos. No obstante, cuando no tenemos que hacer un tratamiento específico para cada caso, está mejor usar la opción más corta.

El script necesita N parámetros

Si tenemos que comprobar un número de parámetros concretos, vamos a comparar con la variable $#. Por ejemplo, necesitamos cinco parámetros que vamos a recorrer con un bucle for.

El script necesita N o más parámetros

Por ejemplo, nuestro script necesita 4 o más parámetros.

El script necesita dos parámetros y queremos mensajes de error específicos

Por ejemplo, un script que necesite que se pase el nombre de un usuario y la ruta de su directorio personal. Si no se pasa el nombre del usuario deberá mostrar un mensaje de error adecuado y terminar la ejecución del script con un código de salida de error.

Si no se pasa la ruta del fichero en el segundo parámetro se deberá mostrar un mensaje de error adecuado y terminar la ejecución del script con un código de salida de error.

  • El script se debe ejecutar por root
  • El script necesita la ruta de un fichero que debe existir
  • El script necesita la ruta de un directorio que debe existir
  • El script necesita el nombre de un usuario que debe existir
  • El script necesita el nombre de un grupo que debe existir
  • El script necesita la ruta de un fichero que no exista
  • El script necesita la ruta de un fichero que exista y que tengamos permiso de lectura
  • El script necesita la ruta de un fichero que exista y que tengamos permiso de lectura y escritura

El script se debe ejecutar por root

El script necesita la ruta de un fichero que debe existir

El script necesita la ruta de un directorio que debe existir

El script necesita el nombre de un usuario que debe existir

Dos comprobaciones, primero que nos pasen parámetro y después que exista el usuario

El script necesita el nombre de un grupo que debe existir

El script debe recibir el nombre de un grupo por parámetro. Si no se pasa parámetro, error adecuado y terminamos con código de salida de error. Si el grupo pasado por parámetro no existe en el sistema, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Como comprobaríamos que el grupo existe? Vamos a la terminal y veamos cómo lo haríamos.

Ahora, lo único que tenemos que hacer es utilizar ese comando en el comando if de forma que si el comando no devuelve un código de salida de correcto, el grupo no existe.

Me pasan usuario, grupo, el usuario existe, el grupo existe y existe un directorio de trabajo para el usuario que debemos configurar

Crea un script que reciba por parámetro obligatoriamente el nombre de una cuenta de usuario y de un grupo.

Si el script no se ejecuta como root, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Si no se pasa el nombre del usuario, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Si no se pasa el nombre del grupo, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Si el usuario no existe en el sistema, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Si el grupo no existe en el sistema, mostramos un mensaje de error adecuado y terminamos la ejecución del script con un código de salida de error.

Si el directorio de trabajo del grupo, con el nombre del grupo dentro del directorio /educatica/2023, no existe, lo creamos y le asignamos como propietario al usuario y cómo grupo al grupo.

Se puede hacer la comprobación de errores con una estructura ¿if..elif..else?

Si, de hecho es más elegante, pero quizá a la hora de razonar en los primeros pasos con scripts puede ser difícil de ver.

Control de muchos errores

Vamos a hacer un script para practicar el control de muchos errores distintos. Se trata de un ejemplo, es raro que tengamos que hacer tantas comprobaciones.

Nuestro script recibirá varios parámetros que son obligatorios, es decir se deben proporcionar. SI no se pasa alguno de estos parámetros, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

El script recibe en el parámetro 1 la ruta de un fichero. Si no se recibe valor, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error..

Si el fichero cuya ruta se ha pasado no existe o no es un fichero, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

En el segundo parámetro se recibe la ruta de un directorio. Si no se pasa valor, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

Si no existe el directorio, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

En el tercer parámetro se obtiene el nombre de un grupo. Si no se pasa valor, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

Si el grupo no existe, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

En el cuarto parámetro, se obtiene el nombre de un usuario. Si no se pasa valor, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

Si el usuario no existe, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

Si no tenemos conexión a internet, se debe mostrar un mensaje de error adaptado al tipo de error y terminar la ejecución del script con un código de salida de error.

Crea un directorio dentro del directorio personal del usuario proporcionado por parámetro con el nombre del grupo. Copia el fichero y el directorio dentro de este directorio recién creado.

Por ejemplo, si se ejecuta

ejemplo.sh datos.txt /var/www/html contabilidad marinapg

El script creará el directorio contabilidad dentro del directorio personal del usuario marinapg. Después copiará tanto el fichero datos.txt como el directorio /var/www/html y todo su contenido en el directorio contabilidad que estará dentro del directorio personal del usuario marinapg.

Solución propuesta 01

Vamos a comprobar si funciona

Versión 02

Vamos a cambiar propietario y grupo del directorio destino y todo su contenido para que sean el usuario y el grupo que nos han pasado por parámetro.

Control de errores más elegante

Se podría hacer el control de errores con if elif.. pero, quizá sea más complicado de entender cuando estamos empezando a hacer scripts.

Dejar una respuesta