Bash scripting

Algunos comandos útiles

Los siguientes comandos son habituales en el trabajo con Bash: head, tail, grep

¿Qué hará el siguiente comando?

grep -d recurse "Jan 2" /var/log/

Actividad 1. Ejecuta el comando lspci, y busca en la salida la información sobre la interfaz de red ethernet. Ahora busca la manera de utilizar lspci en conjunción con el comando grep para que se muestren las 3 líneas anteriores y posteriores a cada aparición de la palabra "Ethernet".

Toma una captura donde se pueda apreciar la ejecución del comando y su salida, y guárdala con el nombre Act1-bashscript.png.

Cut

El comando cut, nos permite extraer partes de archivos: cut

Supón el archivo siguiente, llamado "conf.txt":

valor1=yes valor2=no Esta línea no importa. valor3=default

¿Qué hará el siguiente comando:

cut -s -d "=" -f 1 "conf.txt"

Actividad 2. Extrae del archivo /etc/passwd los nombres de los usuarios, y vuelca el resultado por pantalla.

Entrega una captura llamada Act2-bashscript.png donde se pueda ver la ejecución del comando y su resultado.

Actividad 3. Repite el ejercicio anterior, pero sacando únicamente el último usuario que aparece en /etc/passwd

Entrega una captura llamada Act3-bashscript.png donde sepueda ver la ejecución del comando y su resultado.

Uniq

El comando Uniq nos permite detectar líneas repetidas en un archivo: uniq

Supón el archivo siguiente, llamado "conf2.txt":

valor1=yes valor1=yes valor2=no Esta línea no importa. Esta línea sí improta valor3=default

¿Qué hará el siguiente comando:

uniq -d conf2.txt

Actividad 4. Supón el siguiente archivo:

06-10-14:mensaje 1 03-11-14:mensaje 1 03-12-14:mensaje 1 03-01-15:mensaje 2 07-01-15:mensaje 3

Extrae los mensajes repetidos, sin tener en cuenta la fecha.

Sort

El comando sort nos permite ordenar un conjunto líneas: sort

Supón el archivo del ejemplo anterior, llamado "conf2.txt" con el siguiente contenido:

valor1=yes valor1=yes valor2=no Esta línea no importa. Esta línea sí improta valor3=default

¿Qué hará el siguiente comando?:

sort -t= +1 -2 conf2.txt

Actividad 5. Muestra por pantalla los usuarios que aparecen en el archivo /etc/passwd ordenados por su uid.

Toma una captura con el nombre Act5-bashscript.png, donde se pueda ver el comando y su resultado.

Wc

El comando wc nos permite contar dentro de documentos: wc

Supón el archivo siguiente, llamado "conf3.txt":

campo1 argumento1 argumento2 campo2 argumento3

¿Cómo podríamos comprobar cuantas palabras tiene la primera línea?

¿ ... ?

Actividad 6. El siguiente archivo contiene diferentes líneas referentes a usuarios. Inicialmente aparece el nombre completo del usuario, que puede componerse de 2, 3 o 4 palabras. Después viene el nombre de usuario. Y finalmente la contraseña:

Juan Manuel Gómez Gallardo jgomez 1234 Antonio José Perez Cano aperez 6813 Carlos Jiménez Rodríguez cjimenez 7464 John Staedler jstaedler 4237

Busca la manera de mostrar el número de palabras que tiene una línea concreta del archivo. Es decir, el comando debe poder indicarte cuántas palabras tiene una línea concreta; por ejemplo, ¿Cuántas palabras tiene la línea 3?

Toma una captura donde se pueda ver el comando y su resultado, y guárdala como Act6-bashscript.png

Find

El comando Find nos permite buscar entre archivos y directorios:find

Actividad 7. ¿Cómo encontrarías todos los archivos modificados durante las últimas dos horas por el último usuario añadido al sistema?

Toma una captura donde se muestre la ejecución del comando, llamado Act7-bashscript.png.

Sed

El comando sed permite realizar transformaciones sobre un texto: sed

Actividad 8. Imagina un documento html llamado "pagina1.html" que contiene el siguiente texto:

<html> <head> <title>Título</title> </head> <body> <h1>Utilizando el comando sed</h1> <p1>Sed se utiliza para editar archivos. Ejemplo:</p> <divcode> sed '1,3d' archivo.txt </div> </body> </html>

¿De qué modo harías los siguientes cambios?:

  • <p1> -> <p class="nivel1">
  • <divcode> -> <div class="codigo-fuente">

Toma una captura con la ejecución de los comandos y su resultado, y guárdala con el nombre Act8-bashscript.png

Expresiones regulares

Las expresiones regulares nos permiten crear patrones para buscar coincencias en un texto y procesarlas mediante salgún comando como sed, awk o grep. Para tener una breve referencia a las expresiones regulares básicas, podemos consultar en el siguiente enlace: persoal.citius.usc.es/tf.pena/ASR/Tema_2html/node22.html

Actividad 9. Imagina que tienes un archivo, donde aparecen fechas con el formato mm-dd-aaaa. ¿De qué modo podrías cambiar el formato de dichas fechas a dd del mm del año aaaa?

Toma una captura con el comando, así como su resultado, y guárdala con el nombre Act9-bashscript.png.

Awk

El comando awk permite procesar ficheros con una potencia superior al resto de comandos. Por otra parte, su complejidad es mayor:awk

Actividad 10. Imagina que tienes un archivo como el siguiente:

Pedro de la Rosa prosa 1234 Juan Gómez Gutiérrez jgomez 4321 Antonia Gómez Vicario agomez 9876

Piensa de qué modo podrías generar un archivo como el siguiente:

#!/bin/bash useradd prosa -p 1234 useradd jgomez -p 4321 useradd agomez -p 9876

Toma una captura con el comando y su resultado y guarda la captura con el nombre Act10-bashscript.png.

Redirección de entrada/salida

Todos los comandos toman una entrada y generan una salida. A veces esa entrada no se indica explícitamente, pero siempre hay una. La salida suele ser más evidente, ya que se muestra por pantalla.

Tanto la entrada como la salida de un comando provienen de ficheros. Existen 3 ficheros especiales, que encapsulan el flujo de entrada y de salida. Estos archivos se llaman:

  • stdin - representa el flujo de entrada de datos (procedente del teclado)
  • stdout - representa el flujo de salida de datos sin error (se dirige a la pantalla)
  • stderr - representa el flujo de salida de datos con error (se dirige a la pantalla)

Para conocer más sobre la redirección de entrada salida, podemos consultar en persoal.citius.usc.es/tf.pena/ASR/Tema_2html/node16.html.

A modo descriptivo, la siguiente imagen muestra como se comporta la redirección de E/S.

Actividad 11. Los scripts de bash suelen tener un texto de ayuda que explican el uso del comando. Una forma incómoda de hacer esto, es utilizar el comando echo varias líneas seguidas del siguiente modo:

echo "Descripción: El script miscript.sh procesa un archivo de texto y genera una salida sustituyendo unas palabras por otras." echo "Modo de uso:" echo "El modo general de ejecución del script es el siguiente: miscript.sh [opciones] [arg1 arg2...] nombre_archivo" echo "Opciones:" echo "-o nombre_archivo_salida: Permite indicar un archivo de salida con el nombre \"nombre archivo\"" echo "-s archivo_fuente: Permite indicar los argumentos mediante un archivo de entrada." echo "arg1 arg2: La palabra \"arg1\" se sustituye por la palabra \"arg2\""

Sin embargo, esta estrategia puede hacer que el código sea engorroso, difícil de escribir y de leer. Existe una alternativa, basada en la dirección de entrada/salida. Investiga una forma de formatear el texto de ayuda anterior, pero sin necesidad de escribir contínuamente echo "...". Después, pruébalo siguiendo las siguientes indicaciones:

  1. Crea un nuevo archivo, llamado miscript.sh
  2. Añade al principio del archivo el shebang #!/bin/bash
  3. Escribe a continuación el comando que responde a la pregunta
  4. Modifica los permisos del archivo para que sea ejecutable

Finalmente ejecuta el script y comprueba que funciona.

PISTA: Utiliza la redirección de entrada con etiqueta.

Algunos comandos relacionados con la redirección

El comando tee permite escribir la salida de un comando a un archivo y volver a redirigirla a la salida estándar: tee

Actividad 12. Deseas compilar la última versión disponible del módulo de la interfaz e1000. Mientras el módulo se compila, deseas ver el proceso, pero también quieres que el resultado se guarde en un archivo llamado e1000e.log para su posterior revisión. Encuentra el comando necesario para hacer esto.

Toma una captura con el comando justo antes de ejecutar, y guárdala con el nombre Act12-bashscript.sh

El comando tr permite realizar traducciones de alfabetos equivalentes: tr

Actividad 13. Dispones de un archivo que contiene un texto con varias líneas, tabuladores, tabuladores repetidos, líneas vacías y espacios dobles. Para obtener dicho archivo, ejecuta el siguiente comando:

cat << EOF > loremipsum.txt Lorem ipsum ad his scripta blandit partiendo,$(printf '\t')$(printf '\t') eum fastidii accumsan euripidis in,$(printf '\n') eum liber hendrerit an.$(printf '\t') Qui ut wisi vocibus suscipiantur,$(printf '\t') quo dicit ridens$(printf '\n') inciderint id. $(printf '\t')$(printf '\t')Quo mundi lobortis reformidans eu, legimus senserit definiebas an eos.$(printf '\n') $(printf '\t')$(printf '\t')Eu sit tincidunt incorrupte definitionem, vis mutat affert percipit cu,$(printf '\t')$(printf '\t') eirmod$(printf '\t') consectetuer signiferumque eu per. EOF

¿Cómo podrías utilizar tr para que aparezca todo en una sola línea sin que hayan caracteres de control repetidos?

Toma una captura del comando así como de su resultado, y guárdala con el nombre Act13-bashscript.png.

Las variables

Las variables permiten almacenar un valor temporalmente y procesarlo posteriormente. En el siguiente enlace podemos encontrar información sobre este tema: ovtoaster.com/shell-scripts-en-linux-variables-y-parametros/

Existen diferentes estados de salida a un programa. Podemos utilizar esta información para saber si el comando anterior se ejecutó correctamente o no. El código de estado del comando ejecutado anteriormente se almacena en la variable $?. Para entender cómo usarlo, podemos saber que si el valor es 0 entonces el comando se ejecutó correctamente, y que en otro caso el comando no se ejecutó correctamente. Para conocer algunos códigos de estado de salida importantes, podemos consultar el siguiente enlace: comulinux.blogspot.com.es/2010/03/estado-de-salida-de-un-comando-bash.html.

También puede interesarnos la expansión de parámetros y variables. Podemos consultar este tema en el siguiente enlace: fpg.hol.es/GNU-Linux/expansin_de_parmetros_y_variables.html.

Por último, es importante saber cómo evaluar expresiones aritméticas y comandos: http://es.tldp.org/COMO-INSFLUG/COMOs/Bash-Prog-Intro-COMO/Bash-Prog-Intro-COMO-10.html

Actividad 14. Crea un script, llamado penultimo_argumento.sh que acepta n número de argumentos. Este número de argumentos puede variar de una ejecución a otra. Lo que hace el script penultimo_argumento.sh es lo siguiente:

Mostrar el penúltimo argumento utilizado.

Por ejemplo, si ejecutamos el comando penultimo_argumento.sh div div p span a, el resultado será span.

AYUDA: ${!i} mostraría el argumento número "i", siendo i una variable.

Toma una captura tras ejecutar el script, y guarda el resultado con el nombre Act14-bashscript.sh.

Actividad. Averigua para qué sirve el comando let

Sentencias de control

Las sentencias de control nos permiten aportar lógica a un programa, para tomar decisiones en base a algún criterio. Podemos consultar cómo trabajar con bucles en el siguiente enlace: ovtoaster.com/shell-scripts-en-linux-condicionales-y-bucles/

Actividad 15. Crea un script llamado check_kernel_sources.sh que comprueba si está instalado el código fuente del kernel en ejecución.

  • En caso afirmativo, el script muestra el mensaje siguiente: "El código fuente del kernel <version-kernel> está instalado en la carpeta <ruta-al-codigo-fuente>"
  • En caso negativo, hace lo siguiente:
    1. Informa del problema con el siguiente mensaje: "El código fuente del kernel $lt;version-kernel> no está instalado".
    2. Después muestra al usuario el siguiente mensaje: "¿Desea instalar la última versión del código fuente del kernel?[S/N]:"
    3. Si el usuario elige la opción "S", instala la última versión del código fuente.
    4. En cualquier otro caso, el script termina, mostrando el siguiente mensaje: "No se hará nada".

Guardar el script en un archivo llamada check_kernel_sources.sh.

Funciones

Las funciones nos permiten organizar el código de manera que sea más fácil de mantener y de escribir, dividiéndolo en partes reutilizables. Podemos ver algo sobre funciones en el siguiente enlace: www.adminso.es/index.php/Shell_-_Funciones

Actividad 16. Revisa el ejercicio 13, y añade una función que muestre un mensaje de ayuda por pantalla cuando no se introduzca ningún argumento. La ayuda incluirá el siguiente mensaje:

Script: penultimo_argumento.sh Autor: Fulanito de cuadros. Descripción: El script penultimo_argumento.sh toma un número indeterminado de argumentos, y como resultado muestra el penúltimo. Uso: ./penultimo_argumento.sh arg1 arg2 arg3 arg4 arg5 arg6

Guarda el script con el nombre penultimo_argumento_con_ayuda.sh.

Actividad 17. Escribe un script llamado modprobex.sh que permite instalar módulos del kernel. Su funcionamiento es el siguiente:

  1. modprobex.sh acepta dos parámetros: 1. la carpeta donde está el código fuente del módulo. 2. el nombre del módulo a instalar
  2. tras ejecutar modprobex.sh, comprueba las siguientes cosas:
    • La versión del kernel en ejecución
    • La versión del código fuente del kernel instalado, si es que está instalado
    • El enlace blando build dentro de /lib/modules/version_kernel está correctamente direccionado.
  3. En caso de que la comprobación anterior sea exitosa, lleva a cabo las siguientes tareas:
    1. Averigua la ruta al módulo actualmente instalado, y hace una copia de seguridad del mismo, añadiendo la extensión bk al módulo (por ejemplo, el módulo e1000e.ko pasará a ser e1000e.bk.
    2. Instala el nuevo módulo.
  4. En caso de que la comprobación anterior fracase, lleva a cabo las siguientes tareas:
  5. Informa al usuario del problema.
  6. Pregunta qué se debe hacer: a) Reparar el problema actualizando kernel, así como el código fuente del mismo. b) No hacer nada.
  7. Si el usuario elige reparar el problema, el sistema procede a actualizar el kernel, las fuentes del kernel y finalmente a preguntar al usuario si desea reiniciar el sistema o no.
  8. Si el usuario elige no reparar el problema, el script termina, mostrando un mensaje de fin.

Escribe el script, y guárdalo con el nombre modprobex.sh.

Actividad 18. Escribe un script llamado homebackup.sh que realice una copia de seguridad del directorio home del usuario indicado, manteniendo un registro de las copias de seguridad realizadas. El funcionamiento es como sigue:

  1. homebackup.sh acepta un parámetro: el nombre de un usuario.
  2. Cuando se ejecuta el comando homebackup.sh, se hace una comprobación: si ya se ha hecho una copia de seguridad del usuario en la fecha actual (día, mes y año), se informa de este hecho, y no se hace la copia.
  3. Si no se ha hecho copia de seguridad del usuario en la fecha actual, homebackup.sh hace una copia de la carpeta home del usuario del siguiente modo:
  4. Toma el valor de una variable local, llamada bkfolder, que contiene la ruta al directorio donde se hacen las copias de seguridad.
  5. Después realiza una copia con el comando tar del directorio home del usuario a la ruta indicada por la variable bkfolder. El archivo de copia generado, incluirá en su nombre los siguientes datos:

    • El nombre del usuario.
    • El número de copia, empezando por 0.

    Por ejemplo, si se hace la copia del usuario jperez, y se trata de la segunda copia, el archivo generado se llamará jperez-1.tgz.

  6. Tras hacer la copia de seguridad, añade una línea a un archivo de registro, contenido en la misma carpeta que la copia, llamado bkreg.log, donde se anotará la siguiente información en cada línea:
    • El nombre del usuario.
    • El número de copia.
    • La fecha de la copia, incluyendo día, mes y año.

    Esta información es la utilizada por el script para saber si se debe hacer copia o no.

    Entrega el script con el nombre homebackup.sh

Actividad 19. Disponemos de un archivo como el siguiente:

Antonio Pérez Gómez aperez 1234 estandar Juan Antonio García Gutiérrez jagarcia 2345 admin José González jgonzalez 3456 estandar

En este archivo la información que se muestra es la siguiente:

  • Nombre completo del usuario
  • Nombre de usuario
  • Contraseña del usuario
  • Etiqueta indicando si se trata de un usuario estándar o bien de un administrador (perteneciente al grupo wheel en RHEL/CentOS o al grupo admin en Debian)

Escribe un script llamado crea_usuarios.sh que toma como parámetro la ruta al archivo mostrado anteriormente con los datos de las cuentas, y que a partir de él, crea los usuarios indicados, añadiendo a la cuenta el nombre completo del usuario, asignando la contraseña, y añadiéndolo al grupo wheel en caso de ser necesario.

Actividades propuestas (extra).

  • Crear un script que de a elegir al usuario entre dos contextos A y B. Cada contexto tiene relacionado una configuración diferente. Según el contexto que el usuario elija, se modifica automáticamente la configuración de red, y se reinicia el servicio aplicándola, mostrando finalmente por pantalla la nueva configuración.
  • Queremos replicar los usuarios de un sistema en otro. Para ello, tenemos los archivos passwd, shado y group. Crear un script que cree los nuevos usuarios en el nuevo sistema, de modo que tengan el mismo nombre, igual directorio home, e igual entorno de shell. Además, debe crearse una carpeta adicional en cada carpeta home llamada Extras. El script mostrará una ayuda cuando no se introduzcan argumentos.