miércoles, 23 de agosto de 2017

Trampas

En el Capítulo 10, vimos cómo los programas pueden responder a las señales. También podemos añadir esta capacidad a nuestros scripts. Aunque los scripts que hemos escrito hasta ahora no han necesitado esta capacidad (porque tienen tiempos de ejecución muy cortos, y no crean archivos temporales), los scripts más largos y complicados pueden beneficiarse de tener una rutina de manejo de señales.

Cuando diseñamos un script largo y complicado, es importante considerar qué ocurre si el usuario cierra la sesión o apaga el ordenador mientras el script se está ejecutando. Cuando ocurre un evento como este, debe enviarse una señal a todos los procesos afectados. En respuesta, los programas que representan estos procesos pueden realizar acciones para asegurar una terminación apropiada y ordenada del programa. Digamos, por ejemplo, que hemos escrito un script que crea un archivo temporal durante su ejecución. En nombre del buen diseño, habríamos hecho que el script borre el archivo cuando el script termine su trabajo. También sería inteligente hacer que el script borre el archivo si recibe una señal indicando que el programa va a terminar prematuramente.

bash ofrece un mecanismo para este propósito conocido como trampa. Las trampas se implementan con el comando integrado, apropiadamente denominado, trap. trap usa la siguiente sintaxis:

trap argumento señal [señal...]

donde argumento es una cadena que se leerá y tratará como un comando y señal es la especificación de una señal que pone en funcionamiento la ejecución del comando interpretado.

Aquí tenemos un ejemplo simple:

#!/bin/bash

# trap-demo : simple signal handling demo

trap "echo 'I am ignoring you.'" SIGINT SIGTERM

for i in {1..5}; do
    echo "Iteration $i of 5"
    sleep 5
done

Este script define una trampa que ejecutará un comando echo cada vez que recibe la señal SIGINT o SIGTERM mientras el script se está ejecutando. La ejecución del programa aparece así cuando el usuario intenta detener el script presionando Ctrl-c:

[me@linuxbox ~]$ trap-demo
Iteration 1 of 5
Iteration 2 of 5
I am ignoring you.
Iteration 3 of 5
I am ignoring you.
Iteration 4 of 5
Iteration 5 of 5

Como podemos ver, cada vez que el usuario intenta interrumpir el programa, se muestra el mensaje en su lugar.

Construir una cadena para formar una secuencia útil de comandos puede ser complicado, por lo que es una práctica habitual especificar una función de shell como comando. En este ejemplo, se especifica una función de shell separada para manejar cada señal:

#!/bin/bash

# trap-demo2 : simple signal handling demo

exit_on_signal_SIGINT () {
    echo "Script interrupted." 2>&1
    exit 0
}

exit_on_signal_SIGTERM () {
    echo "Script terminated." 2>&1
    exit 0
}

trap exit_on_signal_SIGINT SIGINT
trap exit_on_signal_SIGTERM SIGTERM

for i in {1..5}; do
    echo "Iteration $i of 5"
    sleep 5
done

Este script presenta dos comandos trap, uno para cada señal. Cada trampa, a su vez, especifica una función de shell a ejecutar cuando se recibe una señal en particular. Fíjate en la inclusión de un comando exit en cada una de las funciones de manejo de señales. Sin un exit, el script continuaría tras completar la función.

Cuando el usuario presione Ctrl-c durante la ejecución de este script, el resultado aparece así:

[me@linuxbox ~]$ trap-demo2
Iteration 1 of 5
Iteration 2 of 5
Script interrupted.

No hay comentarios:

Publicar un comentario